.TITLE TTICH .IDENT /10.00/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; ; 23-JAN-78 PETER WANNHEDEN ; ; PREVIOUSLY MODIFIED BY: ; ; P. WANNHEDEN ; C. F. SPITZ ; D. R. DONCHIN ; T. LEKAS ; J. KAUFFMAN ; S. C. ADAMS ; R. S. PHILPOTT ; L. M. KOGAN ; L. B. MCCULLEY ; M. W. ZAHAREE ; ; MODIFIED FOR RSX-11M-PLUS V4.4 BY: ; ; L. KOGAN 22-MAY-1990 10.00 ; LK757 - FIX THE PROBLEM WITH DELETING CSI ESCAPE SEQUENCE ; ; ;+ ; ****** T T I C H ****** ; ; THIS MODULE CONTAINS THE ROUTINES WHICH MAKE UP THE "PRE-INPUT PROCESS" ; AND THE "INPUT PROCESS" OF THE TERMINAL DRIVER. THE "PRE-INPUT" PROCESS IS ; MODELLED AS RECEIVING CHARACTERS FROM A TERMINAL INTERFACE. THESE CHARACTERS ; ARE INTERPRETED PRIOR TO BEING MOVED TO EITHER A TYPE-AHEAD BUFFER OR TO AN ; OUT-OF-BAND CHARACTER BUFFER. THE "INPUT PROCESS" IS MODELLED AS READING ; CHARACTERS FROM THE TYPE-AHEAD BUFFER, PROCESSING THEM, AND THEN WRITING THEM ; TO AN INPUT BUFFER. THE PROCESSING INVOLVES RECOGNIZING ESCAPE SEQUENCES, ; EDIT CHARACTERS, AND TERMINATORS AND INITIATING THE ECHO PROCESSING OF THE ; CHARACTER. AN INPUT BUFFER CAN BE A USER TASK BUFFER, "BUFFERED INPUT" ; BUFFERS, OR UNSOLICITED INPUT (CLI) BUFFERS. ;- ; .SBTTL .MCALLS AND SYMBOL DEFINITIONS .IF DF R$$MPL .MCALL KRBDF$ KRBDF$ ;DEFINE KRB SYMBOLS .IFF ;R$$MPL .MCALL SCBDF$ SCBDF$ ,,SYSDEF ;DEFINE SCB SYMBOLS .ENDC ;R$$MPL .MCALL PKTDF$ PKTDF$ ;DEFINE PACKET SYMBOLS .IF DF T$$TSA .MCALL EVNDF$ EVNDF$ ;DEFINE TSA EVENT PACKET OFFSETS .ENDC ;T$$TSA .PSECT MAP5.6 .PAGE .SBTTL TERMINAL DRIVER PRE-INPUT PROCESS .SBTTL . ICHAR1 - INITIALIZATION AND SPECIAL CHARACTER CHECKING ; ;+ ; **-ICHAR1 - PROCESS AN INPUT CHARACTER BEFORE TYPE-AHEAD BUFFER ; ; THIS ROUTINE INITIATES PROCESSING OF A CHARACTER ON THE "OUTSIDE" (HARDWARE ; SIDE) OF THE TYPE-AHEAD BUFFER. ANY OF THE FOLLOWING ACTIONS MAY BE TAKEN: ; ; 1. IF THE UNIT IS OFFLINE OR WAITING FOR CARRIER, THE INPUT ; CHARACTER IS IGNORED. ; 2. PERFORM AUTOBAUD DETECTION IF REQUIRED. ; 3. CHECK FOR USER REQUEST TO SWITCH TO TERMINAL MANAGEMENT MODE. ; 4. DISPATCH TO ONE OF THE "PRE-INPUT PROCESS" SPECIAL CHARACTER ; HANDLING ROUTINES (^S, ^Q, ^O, ^X, ^C, ^V). NOTE THAT ; THESE CHARACTERS ARE NOT INTERPRETED IF "PASSTHRU" OR A ; "READ WITH SPECIAL TERMINATORS" IS IN EFFECT. ; 5. PERFORM OUT-OF-BAND CHARACTER DETECTION. ; 6. TRANSFER CONTROL TO "I1DEF" FOR FURTHER PROCESSING. ; ; INPUTS: ; R2 = CHARACTER (LOW BYTE) AND STATUS (HIGH BYTE) ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; R2 = CHARACTER (IF CONTROL PASSED TO "I1DEF") ; ; REGISTERS ALTERED: R2, R3, R4 ;- ; ICHAR1:: .IF DF T$$MOD BITB #US.CRW,U.STS-U.TSTA(R5) ;;;IS THIS UNIT WAITING FOR CARRIER? BNE I1RET ;;;IF NE, YES...IGNORE INPUT .ENDC ;T$$MOD .IF DF R$$CON BITB #US.OFL,U.ST2-U.TSTA(R5) ;;;IS THIS UNIT OFFLINE? BNE I1RET ;;;IF NE, YES...IGNORE INPUT .ENDC ;R$$CON .IF DF T$$SPL MOV U.TAPR-U.TSTA(R5),@#KDSAR5 ;;;MAP THE UCBX AND TABUF .ENDC ;T$$SPL ; ; PERFORM AUTOBAUD DETECTION IF NECESSARY. ; .IF DF D$$M11!D$$ZMD!D$$VMD ASSUME S5.ABP,100000 TST U.TST5-U.TSTA(R5) ;;;IS AUTO-BAUD DETECTION IN PROGRESS? BPL 10$ ;;;IF PL, NO...SKIP CALL SETSPD ;;;DETERMINE THE CALLER'S BAUD RATE BEQ I1RET ;;;IF EQ, DID NOT FIND SPEED...RETURN ;;;ELSE, THE INPUT CHARACTER IN R2 IS A 10$: .ENDC ;D$$M11!D$$ZMD!D$$VMD .IF DF T$$ACD BIS #UA.ACC!UA.PRO!UA.ECH,U.AFLG-U.TSTA(R5) ;;;SET DEFAULT FLAGS BIC #UA.TYP,U.AFLG-U.TSTA(R5) ;;; TST U.ACB-U.TSTA(R5) ;;;DOES THIS TERMINAL HAVE AN ACD? BEQ 20$ ;;;IF EQ, NO...SKIP ACD STUFF MOV R0,-(SP) ;;;SAVE REGISTER NEEDED FOR CALL MOV #A.RECE,R0 ;;;SPECIFY CHARACTER RECEPTION ENTRY POINT CALL $SWACD ;;;CALL ACD MOV (SP)+,R0 ;;;RESTORE REGISTER BIT #UA.ACC,U.AFLG-U.TSTA(R5) ;;;ACCEPT THIS CHARACTER? BEQ I1RET ;;;IF EQ, NO...JUST IGNORE IT BIT #UA.TYP,U.AFLG-U.TSTA(R5) ;;;FORCE THIS CHARACTER INTO TABUF? BNE I1BUFR ;;;IF NE, YES...GO DO IT BIT #UA.PRO,U.AFLG-U.TSTA(R5) ;;;INTERPRET THIS CHARACTER? BEQ I1DEF ;;;IF EQ, NO...SKIP 20$: .ENDC ;T$$ACD ; ; CHECK FOR HARD RECEIVE ERRORS ON THE INPUT CHARACTER. IT IS ASSUMED THAT ; THE ERROR BITS PASSED FROM THE HARDWARE MATCH THE FLAG VALUES IN THE UCB ; STATUS WORD (U.TST5). ; .IF DF T$$RED BIC #^C,R2 ;;;CLEAR EXTRANEOUS BITS BIT #S5.BCC!S5.DAO!S5.VER,R2 ;;;HARD RECEIVE ERROR DETECTED? BNE I1DEF ;;;IF NE, YES...DON'T INTERPRET CHARACTER .IFF ;T$$RED BIT #S5.BCC!S5.DAO!S5.VER,R2 ;;;HARD RECEIVE ERROR DETECTED? BNE I1BEEP ;;;IF NE, YES...RESPOND WITH A BELL .ENDC ;T$$RED BIT #S3.8BC,4(R5) ;;;PASS 8 BITS TO THE USER? BNE 40$ ;;;IF NE, YES...SKIP BIC #200,R2 ;;;OTHERWISE, CLEAR THE HIGH BIT 40$: ; ; CHECK FOR POTENTIAL SWITCH INTO TERMINAL MANAGEMENT MODE. ; .IF DF T$$SCA CALL TMMCHK ;;;SEE IF INPUT PUTS US IN TERMINAL MGMT MODE BCS I1RET ;;;IF CS, ONE OF SWITCH CHARS SEEN...ALL DONE .ENDC ;T$$SCA ; ; SCAN PRE-INPUT PROCESS CHARACTER RECOGNITION TABLE AND THE OUT-OF-BAND ; CHARACTER DEFINITIONS FOR THE CURRENT INPUT CHARACTER. ; MOV #I1CRT,R3 ;;;GET CHARACTER RECOGNITION TABLE CMPB R2,(R3)+ ;;;CONTROL-S? BEQ 50$ ;;;IF EQ, YES...CHECK TTSYNC STATE CMPB R2,(R3)+ ;;;CONTROL-Q? BNE 60$ ;;;IF NE, NO...SKIP TO CONTINUE CHECKS 50$: BIT #S1.TSY,(R5) ;;;TERMINAL HAVE TTSYNC ENABLED? BEQ 60$ ;;;IF EQ, NO...SKIP ASR R3 ;;;CONTROL-S (ASSUMES I1CRT WORD-ALIGNED)? BCS I1CTS ;;;IF CS, YES...HANDLE IT BR I1CTQ ;;;ELSE, IT WAS CONTROL-Q...HANDLE IT 60$: BIT #S1.PTH,(R5) ;;;TERMINAL SET TO PASSTHRU MODE? BNE I1DEF ;;;IF NE, YES...SKIP .IF DF T$$OOB MOV R0,-(SP) ;;;SAVE REGISTER CALL OOBCHK ;;;SEE IF CHARACTER IS OUT-OF-BAND BCC 70$ ;;;IF CARRY CLEAR, NOT OOB CALL OOBCK2 ;;;DO FURTHER CHECKING AND PROCESSING OF OOB MOV (SP)+,R0 ;;;RESTORE REGISTER BCS I1DEF ;;;IF CS THEN OOB INCLUDE BR I1RET ;;;ELSE, NOT INCLUDED 70$: MOV (SP)+,R0 ;;;RESTORE REGISTER ;;;ELSE, CHARACTER NOT OOB OR IS "OOB INCLUDE" MOV #I1CRT+2,R3 ;;;RESTORE POINTER INTO CHAR. RECOGNITION TABLE .ENDC ;T$$OOB CMPB R2,(R3)+ ;;;CONTROL-O? BEQ I1CTO ;;;IF EQ, YES...CHECK IT OUT BIT #S1.RSP,(R5) ;;;READ WITH SPECIAL CHARACTER PROCESSING? BNE I1DEF .IF DF T$$CTX CMPB R2,(R3)+ ;;;CONTROL-X? BEQ I1CTX ;;;IF EQ, YES...CHECK IT OUT .ENDC ;T$$CTX CMPB R2,(R3)+ ;;;CONTROL-C? BEQ I1CTC ;;;IF EQ, YES...PROCESS CONTROL-C ;;;ELSE, FALL THROUGH TO I1DEF .PAGE .SBTTL . I1DEF - NORMAL CHARACTER PROCESSING ; ;+ ; **-I1DEF - HANDLE INPUT CHARACTER THAT HAS NO PRE-INPUT PROCESS SIGNIFICANCE ; ; THIS ROUTINE ACCEPTS A CHARACTER FROM "ICHAR1" AND DOES THE FOLLOWING: ; ; 1. IF THE TYPE-AHEAD BUFFER IS EMPTY, CALL "IPROC" TO SEE IF THE ; CURRENT CHARACTER CAN BE PROCESSED IMMEDIATELY (BY "ICHAR2"). ; 2. IF THE TYPE-AHEAD BUFFER IS NOT EMPTY OR "IPROC" INDICATES THE ; CURRENT CHARACTER CANNOT BE PROCESSED NOW, THE CHARACTER ; IS PLACED INTO THE TYPE-AHEAD BUFFER. ; 3. IF AN ERROR WAS PREVIOUSLY DETECTED, OR THE TYPE-AHEAD BUFFER ; IS FULL, THE CHARACTER IS DISCARDED AND A BELL IS ECHOED. ; ; INPUTS: ; R2 = CURRENT CHARACTER TO BE PROCESSED ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; R2 = CHARACTER (IF CONTROL IS PASSED TO "ICHAR2") ; THE CHARACTER IS PLACED IN THE TABUF IF "ICHAR2" CANNOT BE CALLED ; ; REGISTERS MODIFIED: R3, R4 ;- ; I1DEF: .IF DF T$$SPL MOV #120000+U.TTBF,R3 ;;;SET POINTER TO TABUF .IFF ;T$$SPL MOV U.TTAB-U.TSTA(R5),R3 ;;;GET TABUF POINTER BEQ I1DEF1 ;;;IF EQ, NONE...SKIP BIT #1,R3 ;;;IS THIS A SINGLE-CHARACTER TABUF? BNE I1BEEP ;;;IF NE, YES...TABUF IS FULL SO RING A BELL .ENDC ;T$$SPL TSTB 2(R3) ;;;ANY CHARACTERS ALREADY BUFFERED? BNE I1BUFR ;;;IF NE, YES...SKIP TO BUFFER THIS ONE ALSO ; ; I1DEF1 - NOTHING IS CURRENTLY BUFFERED. CHECK TO SEE IF WE NEED TO ; REQUEST A FORK FOR AN INPUT COUNT STATE TRANSITION. ; I1DEF1: .IF DF T$$ICS ASSUME S1.IBY,200 TSTB (R5) ;;;IS INPUT ALREADY BUSY? BMI 10$ ;;;IF MI, YES...WON'T NEED TO SEND ICS BIT #S3.ICE,4(R5) ;;;IS INPUT COUNT STATE AST ENABLED? BEQ 10$ ;;;IF EQ, NO...TRY TO PROCESS CHARACTER NOW .IF DF T$$SCA BIT #S5.TMM,U.TST5-U.TSTA(R5) ;;;TERMINAL IN TERM. MANGT. MODE? BNE 10$ ;;;NE -> YES= -> DON'T SENT ICS .ENDC ;T$$SCA MOV #FR.ICS,R3 ;;;SET REQUEST FOR INPUT COUNT STATE TRANSITION CALL FORK ;;;REQUEST THE FORK BR I1BUFR ;;;CAN'T PROCESS CHARACTER NOW, SO BUFFER IT 10$: .ENDC ;T$$ICS ; ; CHECK TO SEE IF CURRENT CHARACTER CAN BE PROCESSED RIGHT AWAY ; CALL IPROC ;;;CAN WE PROCESS THE CHARACTER NOW? BCC ICHAR2 ;;;IF CC, YES...GO DO IT ; ; I1BUFR - CHARACTER CANNOT BE PROCESSED NOW. PUT IT IN THE TYPE-AHEAD BUFFER. ; I1BUFR: .IF DF T$$RED BIT #S5.BCC!S5.DAO!S5.VER,U.TST5-U.TSTA(R5) ;;;PREVIOUS HARD ERROR? BNE I1BEEP ;;;IF NE, YES...REJECT THIS CHARACTER MOV R2,-(SP) ;;;COPY CHARACTER PLUS ERROR FLAGS CLRB (SP) ;;;CLEAR LOW BYTE - LEAVE FLAGS IN HIGH BYTE BIS (SP)+,U.TST5-U.TSTA(R5) ;;;SAVE ERROR FLAGS (IF ANY) FOR LATER .ENDC ;T$$RED CALL PCTAB ;;;PUT THIS CHARACTER IN THE TYPE-AHEAD BUFFER BCS I1BEEP ;;;IF CS, TYPE-AHEAD BUFFER FULL...RING BELL I1RET: RETURN ;;;ALL DONE ; ; SOME EVENT REQUIRES ECHOING A BELL AT THE USER'S TERMINAL. ; I1BEEP: CALLR BELL ;;;SOME ERROR REQUIRES ECHOING A BELL .PAGE .SBTTL . SPECIAL CHARACTER PROCESSING ROUTINES .SBTTL . I1CTS - CONTROL-S HANDLING ; ; I1CTSL - LOCK OUT INTERRUPTS AND STOP TERMINAL OUTPUT ; I1CTSL: CALL LOCKI ;LOCK OUT INTERRUPTS I1CTS: BIS #S2.CTS,2(R5) ;;;SET CONTROL-S FLAG MOV #CT.STP,R2 ;;;SET INDEX FOR "STOP OUTPUT" CALLR CTRD ;;;CALL CONTROLLER DEPENDENT ROUTINE .SBTTL . I1CTQ - CONTROL-Q HANDLING ; ; I1CTQL - LOCK OUT INTERRUPTS AND RESUME TERMINAL OUTPUT ; I1CTQL:: CALL LOCKI ;LOCK OUT INTERRUPTS I1CTQ: BIC #S2.CTS,2(R5) ;;;CLEAR CONTROL-S FLAG MOV #CT.RES,R2 ;;;SET INDEX FOR "RESUME OUTPUT" BITB #US.OIU,U.STS-U.TSTA(R5) ;;;EXPECTING AN OUTPUT INTERRUPT? BNE I1RET ;;;IF NE, NO...JUST EXIT I1CTRD: CALLR CTRD ;;;CALL CONTROLLER DEPENDENT ROUTINE .PAGE .SBTTL . I1CTO - CONTROL-O HANDLING ; ; I1CTO - PROCESS OUTPUT DISCARD REQUEST. IF TASK OUTPUT IS IN PROGRESS, ; IT IS ABORTED. IF THE TERMINAL IS ATTACHED, THE OUTPUT DISCARD ; STATE FLAG IS COMPLEMENTED TO ENABLE/DISABLE FURTHER OUTPUT. ; I1CTO: TST U.ATT-U.TSTA(R5) ;;;IS THE TERMINAL ATTACHED? BEQ 10$ ;;;IF EQ, NO...JUST ABORT CURRENT OUTPUT BIT #S2.CTO,2(R5) ;;;IS OUTPUT ALREADY BEING DISCARDED? BNE 30$ ;;;IF NE, YES...SKIP TO ENABLE FURTHER OUTPUT BIS #S2.CTO,2(R5) ;;;SET FLAG TO DISABLE FURTHER OUTPUT 10$: .IF DF T$$SPL MOV #120000,R4 ;;;SET POINTER TO THE UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET POINTER TO THE UCBX BEQ 40$ ;;;IF EQ, NONE...IGNORE CONTROL-O .ENDC ;T$$SPL MOV U.TCO(R4),R3 ;;;GET CURRENT OUTPUT PACKET BEQ 40$ ;;;IF EQ, NOT DOING TASK OUTPUT...ALL DONE BITB #US.OIU,U.STS-U.TSTA(R5) ;;;EXPECTING AN OUTPUT INTERRUPT? BNE 40$ ;;;IF NE, NO...ALL DONE .IF DF T$$RPR TST U.TFPB(R4) ;;;IS OUTPUT FROM A READ W/PROMPT? BNE 20$ ;;;IF NE, YES...CONTROL-O IS IGNORED DURING IT .ENDC ;T$$RPR BITB #TF.WBT,I.FCN(R3) ;;;WRITE-BREAKTHROUGH IN PROGRESS? BNE 40$ ;;;IF NE, YES...IGNORE CONTROL-O 20$: INC (R3) ;;;SET OUTPUT COMPLETION STATUS TO IS.SUC CALL ABOX ;;;ABORT OUTPUT CALLR ODONE ;;;SIMULATE FINAL INTERRUPT ; ; EXIT FROM THE OUTPUT DISCARD STATE. ; 30$: BIC #S2.CTO,2(R5) ;;;CLEAR OUTPUT DISCARD FLAG 40$: RETURN .PAGE .SBTTL . I1CTC - CONTROL-C HANDLING ; ; I1CTC - FLUSH TYPE-AHEAD BUFFER, THEN PASS CONTROL-C TO INPUT PROCESS. ; I1CTC: .IF DF T$$SCA BIT #S3.TME,4(R5) ;;;IS TERMINAL MANAGEMENT MODE ENABLED? BNE I1DEF ;;;IF NE, YES...DON'T RECOGNIZE CONTROL-C HERE .ENDC ;T$$SCA CALL I1CTX1 ;;;FLUSH TABUF CALL I1CTQ ;;;RESUME OUTPUT IF IT WAS STOPPED MOVB #CH.CTC,R2 ;;;RESTORE CHARACTER BR I1DEF1 ;;;GO PROCESS THE CONTROL-C .SBTTL . I1CTX - CONTROL-X HANDLING ; ; I1CTXL - FLUSH TYPE-AHEAD BUFFER AND ENABLE UNSOLICITED ASTS IF NECESSARY. ; I1CTXL:: CALL LOCKI ;LOCK OUT INTERRUPTS I1CTX: I1CTX1: .IF DF T$$RED BIC #S5.BCC!S5.DAO!S5.VER,U.TST5-U.TSTA(R5) ;;;CLEAR ERROR FLAGS .ENDC ;T$$RED ; ; UNLOCK UNSOLICITED INPUT AST CONTROL BLOCK IF THERE IS ONE. ; .IF DF T$$CCA .IF DF T$$SPL MOV 120000+U.TAST,R3 ;;;GET UNSOLICITED INPUT AST BLOCK IF ONE .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET UCBX BEQ 10$ ;;;IF EQ, NONE...SKIP MOV U.TAST(R4),R3 ;;;GET UNSOLICITED INPUT AST BLOCK IF ONE .ENDC ;T$$SPL BEQ 10$ ;;;IF EQ, NONE...SKIP BICB #AF.LCK,A.PRM+5(R3) ;;;UNLOCK AST BLOCK IN CASE IT WAS LOCKED 10$: .ENDC ;T$$CCA ; ; FLUSH THE TYPE-AHEAD BUFFER BY RESETTING THE FILL AND RETRIEVAL POINTERS ; AND THE NUMBER OF ACTIVE BYTES. ALSO CALL SNDXON WHICH WILL OUTPUT AN ; XON IF WE HAVE PREVIOUSLY OUTPUT AN XOFF. ; .IF DF T$$SPL MOV #120000+U.TTBF,R3 ;;;SET POINTER TO TABUF .IFF ;T$$SPL MOV U.TTAB-U.TSTA(R5),R3 ;;;GET TABUF POINTER BEQ 20$ ;;;IF EQ, NONE...NOTHING TO RESET BIT #1,R3 ;;;IS THIS A SINGLE-CHARACTER TABUF? BEQ 30$ ;;;IF EQ, NO...SKIP TO RESET LARGE TABUF CLR U.TTAB-U.TSTA(R5) ;;;FLUSH SINGLE-CHARACTER TABUF 20$: RETURN ;;;ALL DONE 30$: .ENDC ;T$$SPL CLR (R3)+ ;;;INITIALIZE STORE AND RETRIEVAL POINTERS CLRB (R3) ;;;CLEAR NUMBER OF ACTIVE BYTES CALLR SNDXON ;;;SEND AN XON IF NECESSARY .PAGE .SBTTL TERMINAL DRIVER INPUT PROCESS .SBTTL . ICHAR2 - INITIALIZATION AND INPUT STATE RECOGNITION ; ;+ ; **-ICHAR2 - INITIATE PROCESSING OF INPUT CHARACTER. ; ; THIS ROUTINE INITIATES PROCESSING OF A CHARACTER ON THE "INSIDE" (SOFTWARE ; SIDE) OF THE TYPE-AHEAD BUFFER. IT IS ENTERED FROM "I1DEF" ABOVE AND FROM ; "NXTIC" IN MODULE TTODN WHEN A CHARACTER HAS BEEN REMOVED FROM THE TYPE- ; AHEAD BUFFER FOR PROCESSING. AN ALTERNATE ENTRY POINT "ICH2A" IS CALLED ; DURING POST-FORK PROCESSING (ROUTINE "FPPFP" IN MODULE TTCIS). THE ; FOLLOWING ACTIONS MAY BE PERFORMED: ; ; 1. IF RECEIVER ERROR DETECTION IS SUPPORTED (T$$RED) AND THE CURRENT ; CHARACTER CAUSED AN ERROR, THE PENDING INPUT IS TERMINATED ; WITH AN APPROPRIATE COMPLETION STATUS. ; 2. CONVERSION FROM LOWER TO UPPER CASE IS PERFORMED IF NECESSARY. ; 3. THE CHARACTER IS SAVED IN THE SINGLE-CHARACTER ECHO BUFFER. ; 4. THE INTER-CHARACTER ARRIVAL TIMER IS RESET. ; 5. DISPATCH TO A PROCESSING ROUTINE DEPENDING ON THE CURRENT INPUT ; STATE OR THE TYPE OF CHARACTER BEING PROCESSED. ; 6. PASS CONTROL TO "I2ECHO" TO INITIATE NECESSARY ECHOING FOR THE ; INPUT CHARACTER. ; ; INPUTS: ; R2 = CHARACTER ; R5 => U.TSTA OF THE TERMINAL UCB ; IF THE CHARACTER WILL NEED ECHOING, OUTPUT MUST BE IDLE. ; ; OUTPUTS: ; R2 = CHARACTER (IF CONTROL PASSED TO "I2ECHO") ; R4 => UCBX FOR THE TERMINAL ; ; REGISTERS ALTERED: R2, R3, R4 ;- ; ICHAR2:: .IF DF T$$SPL MOV #120000,R4 ;;;SET POINTER TO THE UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET UCBX POINTER BEQ I1RET ;;;IF EQ, NONE...RETURN (COULD HAPPEN... ;;; ...WHEN CTRL-C IS TYPED ON AN IDLE... ;;; ...SLAVED TERMINAL, FOR EXAMPLE) .IFTF ;T$$SPL .IF DF T$$RED ; ; EXAMINE THE INPUT CHARACTER TO DETECT A HARD RECEIVE ERROR. IF THERE IS ; ONE, TERMINATE THE CURRENT INPUT WITH AN APPROPRIATE STATUS. ; BIT #S5.BCC!S5.DAO!S5.VER,R2 ;;;ANY HARD RECEIVE ERRORS? BEQ 20$ ;;;IF EQ, NO...SKIP ERROR CHECKING MOV #IE.DAO&377,R3 ;;;ASSUME ERROR DUE TO DATA OVERRUN ASSUME S5.DAO,40000 ROL R2 ;;;DATA OVERRUN? BMI 10$ ;;;IF MI, YES...RETURN ERROR MOV #IE.BCC&377,R3 ;;;ASSUME FRAMING ERROR OCCURRED ASSUME S5.BCC,S5.DAO/2 ROL R2 ;;;FRAMING ERROR? BMI 10$ ;;;IF MI, YES...RETURN ERROR MOV #IE.VER&377,R3 ;;;ELSE, ERROR MUST BE PARITY ERROR 10$: ASSUME U.TCI,0 MOV R3,@(R4)+ ;;;STORE ERROR CODE JMP IDONE ;;;FINISH THE INPUT REQUEST 20$: .ENDC ;T$$RED .IFT ;T$$SPL MOVB R2,U.TECO-U.TSTA(R5) ;;;SAVE THE CHARACTER BEING PROCESSED .IFF ;T$$SPL MOVB R2,U.TECB(R4) ;;;SAVE THE CHARACTER BEING PROCESSED .ENDC ;T$$SPL ; ; RESET THE INTER-CHARACTER ARRIVAL TIMER. ; .IF NE T$$UTO MOVB #T$$UTO,U.TITI(R4) ;;;INITIALIZE INPUT TIMER .ENDC ;T$$UTO ASSUME S1.USI,100000 TST (R5) ;;;ARE WE DOING UNSOLICITED INPUT? BMI 30$ ;;;IF MI, YES...SKIP ASSUME U.TCI,0 MOV (R4),R3 ;;;GET CURRENT INPUT REQUEST PACKET MOVB I.PRM+6(R3),U.TITI(R4) ;;;INIT USER-DEFINED TIMER VALUE 30$: ; ; DETERMINE ACTION DEPENDENT ON U.TSTA FLAGS. ; .IF DF T$$ACD BIS #UA.PRO!UA.ECH!UA.PUT,U.AFLG-U.TSTA(R5) ;;;SET DEFAULT FLAGS BIC #UA.SPE!UA.COM!UA.CAL,U.AFLG-U.TSTA(R5) ;;; BIT #S1.RNE,(R5) ;;;DOING READ NO ECHO? BEQ 35$ ;;;BR IF NO BIC #UA.ECH,U.AFLG-U.TSTA(R5) ;;;INDICATE NO ECHO 35$: TST U.ACB-U.TSTA(R5) ;;;DOES THIS TERMINAL HAVE AN ACD? BEQ 40$ ;;;IF EQ, NO...SKIP ACD PROCESSING MOV R0,-(SP) ;;;SAVE REGISTER NEEDED FOR ACD CALL MOV #A.PROC,R0 ;;;SET CHARACTER PROCESSING ENTRY POINT CALL $SWACD ;;;CALL ACD MOV (SP)+,R0 ;;;RESTORE REGISTER BIT #UA.PRO,U.AFLG-U.TSTA(R5) ;;;PROCESS THIS CHARACTER AS IS? BEQ I2ECHO ;;;IF EQ, NO...TREAT AS READ-PASS-ALL 40$: .ENDC ;T$$ACD BIT #S3.RUB,4(R5) ;;;RUB-OUT IN PROGRESS? BEQ 50$ ;;;SKIP IF NO JMP I2RUB1 ;;;DO RUBOUT SEQUENCE 50$: .IF DF T$$ESC BIT #S1.ESC,(R5) ;;;IN AN ESCAPE SEQUENCE? BEQ 60$ ;;;IF EQ, NO...SKIP JMP I2ESC2 ;;;CONTINUE WITH THE ESCAPE SEQUENCE 60$: .IFTF ;T$$ESC .IF DF T$$OOB MOV R4,-(SP) ;;;SAVE REGISTERS... MOV R0,-(SP) ;;;THAT ARE DESTROYED BY OOBCHK CALL OOBCHK ;;;WAS THIS CHAR. OOB? MOV (SP)+,R0 ;;;RESTORE REGISTERS MOV (SP)+,R4 ;;;... BCS I2ECHO ;;;CS->OOB->NO SPECIAL FUNCTIONS .ENDC ;T$$OOB BIT #S1.RST,(R5) ;;;READ WITH TERMINATOR TABLE? BEQ 70$ ;;;IF EQ, NOT DOING READ-WITH-TERMINATORS...SKIP .IFT ;T$$ESC ; IF THIS IS NOT AN EXTENDED I/O, CHECK FOR SPECIAL TERMINATORS. ; IF THIS IS EXTENDED I/O, AND THE CHARACTER IS AN ESCAPE WITH ; ESCAPE SEQUENCES RECOGNIZED, ALLOW THIS TO START AN ESCAPE SEQ ; RATHER THAN TERMINATE A READ. .IF DF T$$EIO BIT #S6.EIO,U.TST6-U.TSTA(R5) ;;;EIO? BEQ 65$ ;;;EQ, NOT EIO, CHECK FOR TERMINATOR BIT #U2.ESC,U.CW2-U.TSTA(R5) ;;;DOES TERMINAL GENERATE ESCAPE SEQ.? BEQ 65$ ;;;IF EQ, CHECK FOR RST BIT #S1.RES,(R5) ;;;DOES TASK WANT ESCAPE SEQUENCES? BEQ 65$ ;;;IF EQ,NO .. CHECK FOR RST CMPB R2,#CH.ESC ;;;IS THIS AN ESCAPE? BEQ 70$ ;;;IF ESC, SKIP CHECK FOR RST CMPB R2,#233 ;;;IS THIS A CSI ESCAPE? BEQ 70$ ;;;IF CSI, SKIP CHECK FOR RST 65$: .ENDC ;T$$EIO .ENDC ;T$$ESC CALL I2RST ;;;CHECK FOR A SPECIAL TERMINATOR ;;;IF WE RETURN, CHARACTER WAS NOT TERMINATOR ;;;IF TERMINATOR, STATUS HAS BEEN SET 70$: BIT #S1.PTH,(R5) ;;;TERMINAL IN PASSTHRU ? BNE I2ECHO ;;;IF NE, YES...PROCESS CHARACTER NOW BIT #S1.RSP,(R5) ;;;TERMINAL IN SPECIAL PROCESSING? BNE CASCHK ;;;NE => YES CHECK FOR CASE CONVERSION .SBTTL . ICH2A - DISPATCH DEPENDING ON CURRENT CHARACTER ; ; ICH2A - DETERMINE ACTION DEPENDENT ON CHARACTER. SPECIAL CHARACTERS ARE ; DIVIDED INTO TWO DISPATCH TABLES. IF THE CURRENT CHARACTER IS NOT ; IN THE FIRST TABLE, THE DISPATCH WILL BE TO "EDDEF". HERE, THE ; EDIT CHARACTER (OTHER THAN ^R, ^U, AND DELETE) DISPATCH TABLE IS ; CHECKED. IF NOT IN THAT TABLE, PROCESSING CONTINUES AT "I2DEF". ; .ENABL LSB .IF DF T$$EIO BIT #S1.RNF,(R5) ;;;ARE WE DOING A READ WITH NO FILTER? BNE EDDEF ;;;IF NE, YES...SKIP THE CHECK FOR EDIT CHARS. .ENDC ;T$$EIO ICH2A:: MOV #EDCRT,R3 ;;;POINT TO EDIT CHARACTER RECOGNITION TABLE CMPB R2,#CH.SP ;;;IS CHARACTER IN THIS TABLE? BLO 10$ ;;;IF LO, YES...SCAN THE TABLE CMPB R2,#CH.RUB ;;;ELSE, IS CHARACTER A RUBOUT? BNE I2DEF ;;;IF NE, NO...MUST BE A "NORMAL" CHARACTER BR 10$ ;;;COULD BE IN THIS TABLE ; ; EDDEF - CHARACTER IS NOT IN FIRST RECOGNITION TABLE. SEE IF IT IS AN ; ENABLED EDIT CHARACTER (OTHER THAN ^R, ^U, OR RUBOUT). ; EDDEF:: MOV #I2CRT,R3 ;;;ASSUME WE WANT TO SCAN FIRST TABLE 10$: CALLR CHRDSP ;;;DISPATCH ACCORDING TO CHARACTER .DSABL LSB ; ; I2DEF - IF THE TERMINAL DOES NOT SUPPORT LOWERCASE, SEE IF THE INPUT CHARACTER ; IS ONE OF THE ALTERNATE ESCAPE CHARACTERS (RIGHT BRACE AND TILDE). ; ; EKDEF - COME HERE TO ECHO TERMINATOR IN READ WITH SPECIAL TERMINATORS ; EKDEF:: I2DEF:: CMPB R2,#233 ;;;SPECIAL CASE CSI ESCAPE BNE CASCHK ;;;BRANCH AROUND JMP I2ESC ;;;TO ALLOW IT TO START ESCAPE SEQ. CASCHK: .IF DF T$$EIO BIT #S6.RLU,U.TST6-U.TSTA(R5) ;;;DOING CONVERT TO UPPERCASE? BNE 5$ ;;;BR IF YES .ENDC ;T$$EIO BIT #U2.LWC,U.CW2-U.TSTA(R5) ;;;DOES TERMINAL SUPPORT LOWERCASE? BNE I2ECHO ;;;IF NE, YES...SKIP OTHER ESCAPE CHECKS 5$: BIT #S1.RSP,(R5) ;;;TERMINAL IN SPECIAL PROCESSING? BNE I2CASE ;;;NE => YES => NOT TERM BUT NEEDS CONVERSION CMPB R2,#CH.RBR ;;;IS CHARACTER A RIGHT BRACE? BEQ 10$ ;;;IF EQ, YES...TREAT AS AN ESCAPE CMPB R2,#CH.TLD ;;;IS CHARACTER A TILDE? BNE I2CASE ;;;IF NE, NO...SKIP TO DO CASE CONVERSION ;;;OTHERWISE, TREAT IT AS AN ESCAPE 10$: JMP I2ESC1 ;;;PROCESS ESCAPE CHARACTER AS TERMINATOR ; ; I2CASE - CONVERT LOWER TO UPPER CASE IF REQUIRED. ; I2CASE: CMPB R2,#340 ;;;EIGHT-BIT LOWER CASE CHARACTER? BHI 10$ ;;;IF HIS, YES...CONVERT TO EIGHT-BIT UPPER CASE CMPB R2,#CH.LCZ ;;;UPPER END GRAPHICS? BHI I2ECHO ;;;IF HI, YES...DON'T CONVERT CMPB R2,#CH.LCA ;;;LOWER CASE LETTER? BLO I2ECHO ;;;IF LO, NO...DON'T CONVERT 10$: BICB #40,R2 ;;;CONVERT CHARACTER FROM LOWER TO UPPER CASE .IF DF T$$SPL MOVB R2,U.TECO-U.TSTA(R5) ;;;UPDATE SAVED CHARACTER ALSO .IFF ;T$$SPL MOVB R2,U.TECB(R4) ;;;UPDATE SAVED CHARACTER ALSO .ENDC ;T$$SPL ; ; FALL THRU TO "I2ECHO" TO PROCESS CHARACTER WITHOUT SPECIAL SIGNIFICANCE. ; .PAGE .SBTTL . I2ECHO - INITIATE ECHO OF AN INPUT CHARACTER ; ;- ; **-I2ECHO - PUT CHARACTER IN INPUT BUFFER AND INITIATE ECHOING IF NECESSARY ; ; THIS ROUTINE PROCESSES A CHARACTER THAT HAD NO SPECIAL SIGNIFICANCE DURING ; PROCESSING IN "ICHAR2" AND "ICH2A". THE FOLLOWING ACTIONS MAY OCCUR: ; ; 1. THE CHARACTER IS PLACED IN THE CURRENT INPUT BUFFER. ; 2. IF ECHO IS SUPPRESSED, A TRANSFER IS MADE TO THE "ECHO DONE" ; PROCESSING ROUTINES TO CHECK FOR INPUT COMPLETION. ; 3. ECHO OF THE CHARACTER OR AN EXPANSION OF THE CHARACTER IS ; INITIATED. ; ; INPUTS: ; R2 = CHARACTER ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; IF ECHOING IS REQUIRED, OUTPUT MUST BE FREE. ; ; OUTPUTS: NONE ; ; REGISTERS MODIFIED: R2, R3 ;- ; I2ECHO: .IF DF T$$ACD BIT #UA.PUT,U.AFLG-U.TSTA(R5) ;;;PUT CHARACTER IN INPUT BUFFER? BEQ 10$ ;;;IF EQ, NO...SKIP .IFTF ;T$$ACD BIT #S1.RST,(R5) ;;;DOING READ W/ SPECIAL TERMINATORS BEQ 5$ ;;;IF NOT, THIS SHOULD GO IN BUFFER ASSUME U.TCI,0 TST @(R4) ;;;HAS STATUS BEEN SET? BNE 10$ ;;;IF IT HAS, THIS WAS A TERMINATOR 5$: CALL PUTNIC ;;;PUT CHARACTER IN INPUT BUFFER 10$: .IFT ;T$$ACD BIT #UA.SPE,U.AFLG-U.TSTA(R5) ;;;SPECIAL ECHO REQUESTED? BEQ I2ECHA ;;;IF EQ, NO...SKIP I2SPE: MOV U.ACB-U.TSTA(R5),R2 ;;;GET ACD CONTROL BLOCK ADD #A.IMAP,R2 ;;;POINT TO INTERRUPT BUFFER PARAMETERS OFFSETS MOV (R2)+,U.TOP(R4) ;;;SET ECHO BUFFER APR BIAS (A.IMAP) MOV (R2)+,R3 ;;;SET ECHO BUFFER ADDRESS (A.IBUF) MOV (R2),R2 ;;;SET ECHO BUFFER LENGTH (A.ILEN) CALLR MECHO ;;;OUTPUT THE SPECIAL ECHO USING MULTI-ECHO I2ECHA: BIT #UA.ECH,U.AFLG-U.TSTA(R5) ;;;ECHO THE CHARACTER? BEQ ECHD2 ;;;IF EQ, NO...PRETEND AN ECHO COMPLETED .ENDC ;T$$ACD BIT #S1.RNE,(R5) ;;;IS ECHO SUPPRESSED? BNE ECHD2 ;;;IF NE, YES...PRETEND AN ECHO COMPLETED BIT #S1.PTH,(R5) ;;;IS TERMINAL IN PASSTHRU MODE? BNE I2ECHC ;;;IF NE, YES...ECHO CHARACTER AS ITSELF ; ; I2EXPC - PERFORM CHARACTER EXPANSION AND INITIATE ECHO OF CHARACTER OR STRING. ; I2EXPC: CALL EXPCHR ;;;EXPAND CHARACTER TO GET PROPER ECHO STRING BEQ I2ECHC ;;;IF EQ, SKIP TO ECHO CHARACTER AS ITSELF BCC 10$ ;;;IF CC, NO DEFERRED ECHO IS REQUIRED...SKIP BIS #S1.DEC,(R5) ;;;INDICATE DEFERRED ECHO IS NEEDED 10$: CALLR ECHSTR ;;;ECHO STRING DESCRIBED BY R2 AND R3 ; ; I2ECHC - ECHO THE CHARACTER STORED IN THE SINGLE-CHARACTER ECHO BUFFER. ; I2ECHC: .IF DF T$$SPL MOV R5,R3 ;;;SET UP R3 TO POINT TO THE SINGLE... ADD #U.TECO-U.TSTA,R3 ;;; ...CHARACTER ECHO BUFFER IN THE UCB .IFF ;T$$SPL MOV R4,R3 ;;;SET UP R3 TO POINT TO THE SINGLE... ADD #U.TECB,R3 ;;; ...CHARACTER ECHO BUFFER IN THE UCBX .ENDC ;T$$SPL CALLR ECHCHR ;;;ECHO THE SINGLE CHARACTER POINTED TO BY R3 .PAGE .SBTTL . ECHD1 - COMPLETE PROCESSING OF AN INPUT CHARACTER ; ;+ ; **-ECHD1 - PROCESS COMPLETION OF A CHARACTER OR STRING ECHO. ; ; THIS ROUTINE IS ENTERED WHEN AN ECHO IS DONE. IT PERFORMS ONE OF THE ; FOLLOWING ACTIONS (LISTED FROM HIGHEST TO LOWEST PRIORITY): ; ; 1. IF DEFERRED PROCESSING IS REQUIRED, PICK UP THE CHARACTER ; SAVED IN THE SINGLE-CHARACTER ECHO BUFFER AND PROCESS ; IT FROM THE BEGINNING. ; 2. IF DEFERRED ECHO IS REQUIRED, JUST ECHO THE CHARACTER SAVED ; IN THE SINGLE-CHARACTER ECHO BUFFER. ; 3. IF THE CURRENT INPUT HAS COMPLETED, REQUEST A FORK TO HANDLE IT. ; 4. DISPATCH ON THE CURRENT INPUT STATE VARIABLE (U.TISV). THIS WILL ; EITHER CONTINUE ECHOING OF SPECIAL CASES (E.G. ^R AND ^U) OR ; WILL MAKE A FORK REQUEST TO GET THE NEXT AVAILABLE I/O REQUEST. ; THE ALTERNATE ENTRY POINT "ECHD2" IS ENTERED WHEN PROCESSING FOR A CHARACTER ; IS COMPLETED AND NO ECHOING IS REQUIRED. ; ; INPUTS: ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; S1.OBY = 0 (OUTPUT IDLE) ; ; OUTPUTS: ; UCB UPDATED AS REQUIRED ; ; REGISTERS MODIFIED: R2, R3 ;- ; ECHD1:: MOVB 1(R5),R3 ;;;GET DEFERRED PROCESSING/ECHO FLAGS .IF DF T$$ACD BIT #UA.CAL,U.AFLG-U.TSTA(R5) ;;;CALL ACD BACK FOR MORE ECHO? BEQ 10$ ;;;IF EQ, NO...SKIP MOV R0,-(SP) ;;;SAVE REGISTER MOV #A.CALL,R0 ;;;SET ECHO CALL BACK ENTRY POINT CALL $SWACD ;;;CALL THE ACD MOV (SP)+,R0 ;;;RESTORE REGISTER BR I2SPE ;;;BRANCH BACK TO CONTINUE ECHO OUTPUT 10$: .ENDC ;T$$ACD .IF DF T$$SPL MOVB U.TECO-U.TSTA(R5),R2 ;;;RETRIEVE CHARACTER (IN CASE DEFERRED... ;;; ...PROCESSING OR ECHO IS REQUIRED) .IFF ;T$$SPL MOVB U.TECB(R4),R2 ;;;RETRIEVE CHARACTER (IN CASE DEFERRED... ;;; ...PROCESSING OR ECHO IS REQUIRED) .ENDC ;T$$SPL BIC #S1.DPR!S1.DEC,(R5) ;;;CLEAR DEFERRED PROCESSING/ECHO FLAGS ASSUME S1.DPR,400 ROR R3 ;;;DEFERRED PROCESSING REQUIRED? BCS ICH2A ;;;IF CS, YES...GO DO IT ASSUME S1.DEC,S1.DPR*2 ROR R3 ;;;DEFERRED ECHO REQUIRED? BCS I2EXPC ;;;IF CS, YES...GO DO IT ; ; ECHD2 - CHECK TO SEE IF THE CURRENT INPUT BUFFER HAS BEEN FILLED. ; ECHD2: ; ; EKESC,EKAES - ESCAPE OR ALTERNATE ESC WAS SEEN AS SPECIAL TERMINATOR ; EKESC:: EKAES:: .IF DF T$$ACD BIT #UA.COM,U.AFLG-U.TSTA(R5) ;;;COMPLETE INPUT? BEQ 10$ ;;;IF EQ, NO...SKIP MOV U.ACB-U.TSTA(R5),R3 ;;;GET ACD CONTROL BLOCK MOV A.IOS(R3),@(R4)+ ;;;SET I/O COMPLETION STATUS BR IDONE ;;;FORK TO COMPLETE INPUT 10$: .ENDC ;T$$ACD ASSUME U.TCI,0 TSTB @(R4)+ ;;;HAS A COMPLETION STATUS BEEN SET? BNE IDONE ;;;IF NE, YES...FORK TO COMPLETE THE INPUT TST U.TIC-2(R4) ;;;IS THE CURRENT BUFFER FULL? BNE 20$ ;;;IF NE, NO...SKIP BIT #S1.IBF,(R5) ;;;ARE WE DOING BUFFERED INPUT? BEQ IDONE ;;;IF EQ, NO...FORK TO COMPLETE THE INPUT ; ; WE ARE DOING BUFFERED INPUT, AND JUST FILLED UP THE CURRENT BUFFER. ; SEE IF THERE IS ANOTHER BUFFER LINKED TO THE CURRENT (COULD BE THE ; CASE IF THE OPERATOR DID RUBOUT OR CTRL-U, OR IF WE ARE PROCESSING ; CTRL-R ECHO). IF THERE IS, UPDATE UCB. IF THERE IS NOT, FORK TO GET ; ANOTHER BUFFER. ; ASSUME U.TIP,U.TCI+2 MOV @(R4)+,R2 ;;;GET NEXT BUFFER IF THERE IS ONE BEQ IDONE1 ;;;IF EQ, THERE IS NONE...FORK TO GET ANOTHER ASSUME U.TTIC,U.TIP+6 CMP (R4)+,(R4)+ ;;;POINT TO U.TTIC CALL NXTIB ;;;START USING NEXT BUFFER BEQ IDONE1 ;;;IF EQ, NOT ONE...WE ARE DONE AFTER ALL CMP -(R4),-(R4) ;;;POINT BACK TO U.TIP ; ; CONSULT INPUT STATE VARIABLE TO SEE WHAT TO DO NEXT. NOTE THAT IN AN ESCAPE ; SEQUENCE, THE STATE VARIABLE IS USED WHEN THE NEXT CHARACTER OF THE SEQUENCE ; ARRIVES...NOT WHEN A PREVIOUS CHARACTER HAS BEEN ECHOED, WHERE WE ARE NOW. ; SO IF WE ARE IN AN ESCAPE SEQUENCE, JUST FORK FOR THE NEXT REQUEST PACKET. ; 20$: TST -(R4) ;;;POINT BACK TO TOP OF UCBX .IF DF T$$ESC ; ; THE FOLLOWING ASSUMES THAT THE FIRST ENTRY IN THE INPUT STATE DISPATCH ; TABLE POINTS TO "CFGRQ", WHICH WILL FORK TO GET A NEW REQUEST PACKET. ; CLR R2 ;;;SET UP FOR STATE TABLE DISPATCH BIT #S1.ESC,(R5) ;;;ARE WE IN THE MIDDLE OF AN ESCAPE SEQUENCE? BNE NXSTA1 ;;;IF NE, YES...SKIP NORMAL STATE DISPATCH .ENDC ;T$$ESC ; ; NXSTAT - DISPATCH ON THE CURRENT VALUE OF THE INPUT STATE VARIABLE. THIS WILL ; SEQUENCE THROUGH THE INPUT STATES UNTIL IT FORKS FOR A NEW REQUEST PACKET. ; NXSTAT: MOVB U.TISV(R4),R2 ;;;GET STATE VARIABLE ASL R2 ;;;MAKE WORD INDEX NXSTA1: CALLR @ISDSP(R2) ;;;DISPATCH ON CURRENT INPUT STATE .SBTTL . IDONE - QUEUE FORK REQUEST FOR INPUT REQUEST COMPLETION ; ; IDONE - QUEUE A FORK REQUEST BECAUSE A TERMINATOR CHARACTER WAS SEEN. ; THE LINK WORD IN THE PACKET CONTAINS THE COMPLETION STATUS (IF IT IS ; A SOLICITED READ). THE INPUT STATE FLAGS ARE ALSO RESET ; IDONE1 - QUEUE A FORK REQUEST BECAUSE THE (CURRENT) INPUT BUFFER IS FULL. ; IDONE:: CALL IRESET ;;;RESET THE TERMINAL INPUT STATE FLAGS IDONE1: MOV #FR.IRD,R3 ;;;FORK TO PROCESS INPUT REQUEST COMPLETION CALLR FORK ;;;DO IT .PAGE .SBTTL . SPECIAL INPUT STATE AND CHARACTER PROCESSING ROUTINES .SBTTL . I2RST - READ WITH SPECIAL TERMINATORS ; ;- ; **-I2RST - READ WITH SPECIAL TERMINATORS IS IN PROGRESS ; ; THIS ROUTINE CHECKS THE CURRENT CHARACTER AGAINST THE PRE-DEFINED "SPECIAL ; TERMINATORS" OR AGAINST THE CURRENT USER-SPECIFIED TERMINATOR TABLE TO ; SEE IF THE CURRENT INPUT REQUEST SHOULD BE COMPLETED. IF SO, AND IF THE ; TERMINATOR IS NOT TO BE ECHOED, THE RETURN ADDRESS (FROM "ICHAR2") IS DELETED ; AND THE INPUT IS TERMINATED. IF THE TERMINATOR NEEDS TO BE ECHOED, STATUS ; IS SET AND A RETURN TO ICHAR2 IS EXECUTED FOR ECHO AND TERMINATION. OTHERWISE, ; THE CHARACTER IS RETURNED UNMODIFIED. ; ; INPUTS: ; R2 = CHARACTER ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: NONE ; ; REGISTERS MODIFIED: NONE ;- ; I2RST: MOV R3,-(SP) ;;;SAVE REGISTER USED BY THE ROUTINE TST U.TRTT(R4) ;;;USER-SPECIFIED TERMINATORS PRESENT? BEQ 10$ ;;;IF EQ, NO...SKIP ; ; CHECK CHARACTER AGAINST USER-DEFINED TERMINATOR SET ; MOV R2,R3 ;;;GET A COPY OF THE TYPED CHARACTER BIC #177417,R3 ;;;CLEAR ALL BUT HIGH ORDER 4 BITS .IF DF R$$EIS ASH #-3,R3 ;;;DIVIDE BY 8. .IFF ;R$$EIS ASR R3 ;;;DIVIDE BY 8. ASR R3 ;;; ASR R3 ;;; .ENDC ;R$$EIS ADD U.TRTT(R4),R3 ;;;ADD TABLE BASE ADDRESS TO OFFSET MOV R2,-(SP) ;;;SAVE CURRENT CHARACTER BIC #177760,R2 ;;;THIS TIME LOOK AT LOW ORDER 4 BITS ASL R2 ;;;CONVERT FROM BYTE TO WORD OFFSET BIT $BTMSK(R2),(R3) ;;;SEE IF MATCHES AGAINST TERMINATOR TABLE BEQ 30$ ;;;IF EQ, IT DOESN'T...PROCESS NORMAL CHAR. MOV (SP)+,R2 ;;;RESTORE CHARACTER BR 20$ ;;;CHARACTER IS A TERMINATOR ; ; CHECK CHARACTER AGAINST NORMAL "SPECIAL TERMINATORS". ; 10$: CMPB R2,#CH.SP ;;;IS IT A CONTROL CHARACTER? BLO 20$ ;;;IF LO, YES...IT IS A TERMINATOR CMPB R2,#CH.RBR ;;;IS IT A "NORMAL" CHARACTER? BLO 40$ ;;;IF LO, YES...IT IS NOT A TERMINATOR CMPB R2,#CH.RUB ;;;IS IT A RUBOUT? BEQ 20$ ;;;IF EQ, YES...IT IS A TERMINATOR CMPB R2,# ;;;EIGHT-BIT NON-CONTROL CHARACTER? BHIS 40$ ;;;IF HIS, YES...IT IS NOT A TERMINATOR CMPB R2,#200 ;;;EIGHT-BIT CONTROL CHARACTER? BHIS 20$ ;;;IF HIS, YES...IT IS A TERMINATOR BIT #U2.LWC,U.CW2-U.TSTA(R5) ;;;TERMINAL SUPPORT LOWERCASE? BNE 40$ ;;;IF NE, YES...175-176 ARE NORMAL CHARACTERS ; ; TERMINATOR FOUND - SET COMPLETION STATUS TO IS.SUC WITH THE TERMINATOR ; IN THE HIGH BYTE. ** NOTE ** THE CHARACTER IS NOT STORED IN THE BUFFER. ; 20$: MOV R2,R3 ;;;GET COPY OF CHARACTER SWAB R3 ;;;GET TERMINATOR IN HIGH BYTE CLRB R3 ;;;CLEAR LOW BYTE INC R3 ;;;SET IS.SUC IN LOW BYTE ASSUME U.TCI,0 MOV R3,@(R4) ;;;STORE STATUS MOV (SP)+,R3 ;;;RESTORE R3 TST (SP)+ ;;;GET RID OF RETURN ADDRESS BIT #S1.TNE!S1.RNE,(R5) ;;;SHOULD THIS BE ECHOED? BNE 25$ ;;;IF NO ECHO BR MOV #EKCRT,R3 ;;;CHARACTER RECOGNITION TABLE FOR TERM.ECHO. CALLR CHRDSP ;;;AND DISPATCH 25$: BR IDONE ;;;REQUEST FORK FOR INPUT COMPLETION 30$: MOV (SP)+,R2 ;;;RESTORE CHARACTER 40$: MOV (SP)+,R3 ;;;RESTORE REGISTER 50$: RETURN ;;;BACK TO CALLER .PAGE .SBTTL . I2ESC* - ESCAPE SEQUENCE AND TERMINATOR HANDLING ; ;- ; **-I2ESC - REAL ESCAPE CHARACTER SEEN; POSSIBLY START ESCAPE SEQUENCE ; **-I2AES - ALTERNATE ESCAPE CHARACTER WAS DETECTED ; **-I2ESC1 - TERMINATE INPUT WITH IS.ESC STATUS ; **-I2ESC2 - CONTINUE PROCESSING OF INPUT ESCAPE SEQUENCE ; ; THESE ROUTINES HANDLE ESCAPE AND ESCAPE SEQUENCE PROCESSING AS FOLLOWS: ; ; 1. UPON ENTRY AT I2ESC, IF THE TERMINAL IS SET UP TO GENERATE ; ESCAPE SEQUENCES AND THE ATTACHED TASK CAN ACCEPT THEM, ; ESCAPE SEQUENCE MODE IS ESTABLISHED. OTHERWISE, THE ; ESCAPE TERMINATES THE CURRENT INPUT VIA "I2ESC1". ; 2. ENTRY AT I2AES OCCURS IF AN ALTERNATE ESCAPE CHARACTER WAS ; (OCTAL 37) WAS DETECTED. ; 3. ENTRY AT I2ESC1 WILL CAUSE THE CURRENT INPUT TO BE TERMINATED ; WITH A STATUS OF IS.ESC. ; 4. I2ESC2 IS ENTERED TO PROCESS SUBSEQUENT CHARACTERS OF THE CURRENT ; ESCAPE SEQUENCE. SYNTAX RULES ARE CHECKED DEPENDING ON THE ; INPUT STATE VARIABLE, U.TISV. WHEN THE LAST CHARACTER OF ; A VALID SEQUENCE IS RECEIVED, THE INPUT IS COMPLETED WITH ; THE STATUS IS.ESQ. ; 5. A "RUBOUT" CHARACTER WILL CAUSE ALL CHARACTERS RECEIVED SINCE ; AN ESCAPE CHARACTER TO BE REMOVED FROM THE INPUT BUFFER. ; 6. A SYNTAX ERROR WILL TERMINATE THE INPUT WITH THE STATUS IE.IES. ; ; INPUTS: ; R2 = CURRENT INPUT CHARACTER ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: NONE ; ; REGISTERS MODIFIED: R2, R3, R4 ;- ; I2ESC:: .IF DF T$$ESC BIT #U2.ESC,U.CW2-U.TSTA(R5) ;;;DOES TERMINAL GENERATE ESCAPE SEQ.? BEQ I2ESC1 ;;;IF EQ, NO...TERMINATE INPUT BIT #S1.RES,(R5) ;;;DOES TASK WANT ESCAPE SEQUENCES? BEQ I2ESC1 ;;;IF EQ, NO...SKIP ASSUME S1.USI,100000 TST (R5) ;;;ARE WE DOING UNSOLICITED INPUT? BMI I2ESCU ;;;IF MI, YES...TERMINATE THE INPUT 10$: BIS #S1.ESC,(R5) ;;;ENTER ESCAPE SEQUENCE MODE TSTB R2 ;;;IS THIS CSI ESC? BPL I2ESC3 ;;;BR IF NO MOVB #17,U.TISV(R4) ;;;ESTABLISH OFFSET FOR CSI ESC. SEC. BR I2ESC3 ;;;STORE THE CHARACTER AND EXIT ; ; I2AES - ALTERNATE ESCAPE CHARACTER WAS DETECTED. ; .IFTF ;T$$ESC ;;;LABEL SHOULD ALWAYS BE DEFINED I2AES:: .IFT ;T$$ESC BIT #U2.ESC,U.CW2-U.TSTA(R5) ;;;TERMINAL GENERATE ESCAPE SEQUENCES? BEQ J2EDDF ;;;IF EQ, NO...PROCESS AS A NORMAL CHARACTER .IFTF ;T$$ESC ; ; I2ESC1 - TERMINATE CURRENT INPUT WITH STATUS IS.ESC. ; I2ESC1: BIT #S1.RST,(R5) ;;;READ WITH SPECIAL TERMINATORS? BNE I2ESC3 ;;;BR IF SO (NE) ASSUME U.TCI,0 I2ESCU: MOV #IS.ESC,@(R4)+ ;;;SET COMPLETION STATUS TO IS.ESC BR IDONE ;;;REQUEST A FORK TO COMPLETE THE INPUT .IFT ;T$$ESC ; ; I2ESC2 - PROCESS SUBSEQUENT CHARACTERS OF AN ESCAPE SEQUENCE. ; I2ESC2: CMPB R2,#37 ;;;IS CHARACTER IN RANGE 0-37? BLO 50$ ;;;IF LO, YES...THIS IS A SYNTAX ERROR CMPB R2,#CH.RUB ;;;IS CURRENT CHARACTER A RUBOUT? BEQ RUBESC ;;;IF EQ, YES...DELETE ENTIRE ESCAPE SEQUENCE MOVB U.TISV(R4),R3 ;;;GET CURRENT SYNTAX RULE BNE 10$ ;;;IF NE, NOT FIRST TIME THRU; SO SKIP CMPB U.TTYP-U.TSTA(R5),#T.VT61 ;;;IS THIS A VT61? BNE 10$ ;;;IF NE, NO...SKIP MOV #-6,R3 ;;;SET UP TO ALLOW CERTAIN EXCEPTIONS 10$: ADD #ESCST,R3 ;;;SET POINTER INTO ESCAPE SYNTAX RULE TABLE 20$: CMPB R2,(R3)+ ;;;IS THE INPUT CHARACTER IN RANGE? BLO 30$ ;;;IF LO, NO...CHECK NEXT RANGE CMPB R2,(R3)+ ;;;IN RANGE? BHI 40$ ;;;IF HI, NO...CHECK NEXT RANGE MOVB (R3),U.TISV(R4) ;;;CHARACTER IS OK - SAVE NEXT SYNTAX RULE BNE I2ESC3 ;;;IF NE, NOT DONE YET...STORE CHAR. AND EXIT ; ; ESCAPE SEQUENCE IS COMPLETE - SET STATUS IS.ESQ. ; MOV #IS.ESQ,@U.TCI(R4) ;;;SET RETURN STATUS BR 60$ ;;;FINISH OFF ESCAPE SEQUENCE ; ; CHARACTER DIDN'T MATCH CURRENT RANGE - GET NEXT RANGE FOR CURRENT SYNTAX RULE. ; 30$: INC R3 ;;;UPDATE POINTER 40$: TSTB (R3)+ ;;;ANY MORE RANGES FOR THIS RULE? BNE 20$ ;;;IF NE, YES...LOOP FOR NEXT ONE ; ; THE INPUT CHARACTER IS INVALID IN THE ESCAPE SEQUENCE PROCESSED SO FAR. ; COMPLETE THE CURRENT INPUT REQUEST WITH COMPLETION STATUS "IE.IES". ; 50$: MOV #IE.IES&377,@U.TCI(R4) ;;;SET ERROR STATUS 60$: CALL I2ESCX ;;;GET OUT OF ESCAPE SEQUENCE MODE ; ; I2ESC3 - STORE THE CURRENT CHARACTER OF THE ESCAPE SEQUENCE AND SEE IF ; THE CURRENT INPUT REQUEST HAS COMPLETED. ; .IFTF ;T$$ESC I2ESC3: CALL PUTNIC ;;;STORE CHARACTER AND DON'T ECHO ANYTHING JMP ECHD2 ;;;CHECK FOR COMPLETION OF THE INPUT REQUEST .IFT ;T$$ESC ; ; RUBESC - DELETE THE ENTIRE ESCAPE SEQUENCE FROM INPUT BUFFER AND EXIT FROM ; ESCAPE SEQUENCE MODE. ; RUBESC:: CALL GETPIC ;;;GET PREVIOUS CHARACTER CMPB R2,#CH.ESC ;;;IS THIS THE ESCAPE? BEQ I2ESCX ;;;YES CMPB R2,#233 ;;;CHECK FOR CSI ESCAPE BNE RUBESC ;;;IF NE, NO...LOOP TILL WE FIND IT I2ESCX: BIC #S1.ESC,(R5) ;;;GET OUT OF ESCAPE MODE CLRB U.TISV(R4) ;;;CLEAR STATE VARIABLE RETURN ;;;RETURN J2EDDF: JMP I2DEF ;;;CONTINUE INPUT CHARACTER THROUGH INPUT LOGIC .ENDC ;T$$ESC .PAGE .SBTTL . I2CR - TERMINATE INPUT DUE TO CARRIAGE RETURN ; ; I2CR - CARRIAGE RETURN HAS BEEN INPUT. TERMINATE INPUT WITH STATUS "IS.CR". ; .ENABL LSB I2CR:: CLR -(SP) ;;;ZERO THE ECHO STRING ADJUSTMENT COUNT MOV #IS.CR,-(SP) ;;;SET COMPLETION STATUS TO IS.CR BR 10$ ;;;SKIP TO COMMON CODE .SBTTL . I2CTZ - TERMINATE INPUT DUE TO CONTROL-Z ; ; I2CTZ - CONTROL-Z HAS BEEN INPUT. TERMINATE INPUT WITH STATUS "IE.EOF". ; I2CTZ:: MOV #2,-(SP) ;;;SET ^Z ECHO STRING ADJUSTMENT COUNT MOV #IE.EOF&377,-(SP) ;;;SET COMPLETION STATUS TO IE.EOF 10$: BIT #S1.RST,(R5) ;;;WAS THIS READ W/ SPEC. TERMS? BEQ 12$ ;;;IF EQ, NO. THIS IS A TERMINATOR ; ; COME HERE IF DOING RST. WE HAVE 2 CASES; EITHER THIS IS NOT A TERMINATOR ; AND IS AN INPUT CHARACTER (FIRST PASS THROUGH THIS CODE) OR ELSE, ; THIS IS THE SECOND TIME THROUGH...WE ARE DOING DEFERRED PROCESSING OF ; A TERMINATOR. WE END UP HERE FROM ECHD1 AND HAVE BYPASSED THE RST TEST. ; IF THIS IS THE CASE, A STATUS WILL HAVE BEEN SET. ; TST (SP)+ ;;;GET RID OF STATUS TST @(R4) ;;;STATUS SET? BNE 15$ ;;;NE => YES => TERMINATOR CALL PUTNIC ;;;AND PUT THIS NON-TERMINATOR IN BUFFER BIT #S1.RNE,(R5) ;;;ECHO SUPPRESSED? BEQ 15$ ;;;JOIN COMMON CODE TO ECHO TST (SP)+ ;;;CLEAN STRING ADJUSTMENT OFF STACK JMP ECHD2 ;;;AND GET OUT OF HERE 12$: ASSUME U.TCI,0 MOV (SP)+,@(R4) ;;;ELSE, SET STATUS BIT #S1.RNE!S1.TNE,(R5) ;;;ECHO SUPPRESSED? BNE 30$ ;;;GO SET STATUS AND COMPLETE IO BR 15$ ; ; EKCR AND EKCTZ - OR ^Z WAS SPECIAL TERMINATOR. COME HERE TO ECHO ; EKCR:: CLR -(SP) ;;;ZERO ECHO STRING ADJUSTMENT COUNT BR 15$ ;;;JOIN COMMON CODE EKCTZ:: MOV #2,-(SP) ;;;SET ^Z ECHO STRING ADJUSTMENT COUNT 15$: CALL EXCR1 ;;;EXPAND A CARRIAGE RETURN BCC 20$ ;;;IF CC, NO LEADING LF REQUIRED...SKIP BIS #S1.DPR,(R5) ;;;ELSE DEFER PROCESSING OF CR OR CTRL-Z CLR (SP) ;;;CLEAR ADJUSTMENT COUNT 20$: ADD (SP),R2 ;;;ADJUST COUNT OF BYTES TO ECHO SUB (SP)+,R3 ;;;ADJUST BUFFER POINTER BR C2ECHS ;;;SKIP TO ECHO THE STRING 30$: TST (SP)+ ;;;CLEAN STACK JMP IDONE ;;;COMPLETE THE CURRENT INPUT .DSABL LSB .PAGE .SBTTL . CONTROL-U AND CONTROL-R ECHO PROCESSING .SBTTL . EDCTU - INITIALIZE AND ECHO "^U" ; ; EDCTU - CONTROL-U HAS BEEN INPUT. INITIALIZE ECHO PROCESSING TO BEGIN ; ECHO OF "^U " OR "^U ". ; .ENABL LSB EDCTU:: MOVB #SV.CU1,U.TISV(R4) ;;;INITIALIZE STATE VARIABLE MOV #ASCTU,R3 ;;;GET CTRL-U STRING .IF DF T$$CTR BR 20$ ;;;ECHO ^U .SBTTL . EDCTR - INITIALIZE AND ECHO "^R" ; ; EDCTR - CONTROL-R HAS BEEN INPUT. INITIALIZE ECHO PROCESSING TO BEGIN ; ECHO OF "^R " OR ; "^R ". ; EDCTR:: BIT #S1.RNE,(R5) ;;;IS ECHO SUPPRESSED? BEQ 10$ ;;;IF EQ, NO...WE CAN PERFORM THE ^R FUNCTION CALLR CFGRQ ;;;ELSE, IGNORE AND PROCESS AN OUTPUT REQUEST 10$: MOV U.TIP+2(R4),U.TTOC(R4) ;;;SAVE POS. OF LAST BYTE + 1 MOVB #SV.CR1,U.TISV(R4) ;;;INITIALIZE STATE VARIABLE MOV #ASCTR,R3 ;;;GET CTRL-R STRING .ENDC ;T$$CTR 20$: BIT #S2.FLF,2(R5) ;;;FORCE LF? BEQ 30$ ;;;IF EQ, NO...SKIP BIT #S1.RNE,(R5) ;;;YES, BUT...IS NO ECHO SET? BEQ 25$ ;;;NOPE, DO FORCED LINEFEED BIC #S2.FLF,2(R5) ;;;NO ECHO THUS NO LINEFEED, JUST CLEAR FLAG BR 30$ ;;;AND FINISH UP 25$: BIS #S1.DPR,(R5) ;;;DEFER PROCESSING OF ^U OR ^R CALL EXPCHR ;;;EXPAND CHARACTER IN R2 (JUST TO FORCE LF) BR C2ECHS ;;;MAKE CALL TO ECHO THE EXPANSION STRING 30$: MOV R3,-(SP) ;;;SAVE ADDRESS OF ECHO STRING ASSUME U.TCI,0 MOV (R4)+,R3 ;;;GET CURRENT INPUT PACKET MOV #UPUNB,-(SP) ;;;ASSUME UNBUFFERED INPUT BIT #S1.IBF,(R5) ;;;ARE WE DOING BUFFERED INPUT? BEQ 40$ ;;;IF EQ, NO...CORRECT ASSUMPTION ADD #U.TFIB-2,R4 ;;;POINT TO U.TFIB MOV (R4),R2 ;;;GET FIRST INPUT BUFFER MOV #FPSUI1,(SP) ;;;ASSUME UNSOLICITED INPUT ASSUME S1.USI,100000 TST (R5) ;;;DOING UNSOLICITED INPUT? BMI 40$ ;;;IF MI, YES...CORRECT ASSUMPTION MOV I.PRM+4(R3),-(R4) ;;;SOLICITED INPUT - GET TOTAL BYTE COUNT MOV #NXTIB,(SP) ;;; 40$: CALL @(SP)+ ;;;CALL UPUNB, FPSUI1, OR NXTIB TO UPDATE UCB .IF DF T$$SPL MOV #120000,R4 ;;;RESTORE UCBX POINTER .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;RESTORE UCBX POINTER .ENDC ;T$$SPL MOV (SP)+,R3 ;;;POINT TO ^U OR ^R STRING BIT #S1.RNE,(R5) ;;;ECHO SUPPRESSED? BNE I2CTUE ;;;Y - JUMP (MUST BE ^U) MOV #2,R2 ;;;LENGTH OF ^U OR ^R STRING ; ; DON'T WORRY ABOUT UPDATING CURRENT HORIZONTAL POSITION FOR 2 CHARACTERS. ; WE ARE GOING TO DO A CARRIAGE RETURN IMMEDIATELY AFTER THEM. ; BR C2ECHS ;;;GO ECHO THE STRING DESCRIBED BY R2 AND R3 .PAGE .SBTTL . I2CTU1/I2CTR1 - ECHO AND FILLERS ; ; I2CTU1/I2CTR1 - "^R" OR "^U" HAS BEEN ECHOED. SET UP TO ECHO ; A CARRIAGE-RETURN (PLUS FILLERS). ; I2CTU1:: I2CTR1:: INCB U.TISV(R4) ;;;UPDATE INPUT STATE VARIABLE ASSUME S1.USI,100000 TST (R5) ;;;ARE WE DOING UNSOLICITED INPUT? .IF DF R$$MPL!A$$CLI BPL 50$ ;;;IF PL, NO...SKIP ; ; IN ALTERNATE CLI SYSTEMS, THE CLI PROMPT IS NOT ASSUMED TO START WITH A ; CARRIAGE RETURN, SO DO NOT OUTPUT ONE. RATHER, GO ON TO THE NEXT STATE. ; J2NXST: JMP NXSTAT ;;;DON'T GIVE GRATIS CARRIAGE RETURN 50$: .IFF ;R$$MPL!A$$CLI BMI 70$ ;;;IF MI, YES...ECHO .ENDC ;R$$MPL!A$$CLI .IF DF T$$RPR TST U.TFPB(R4) ;;;READ W/PROMPT IN PROGRESS? BNE 70$ ;;;IF NE, YES...DON'T SKIP NEXT STATE .ENDC ;T$$RPR 60$: INCB U.TISV(R4) ;;;BYPASS THE NEXT ECHO STATE 70$: CALL EXCR1 ;;;EXPAND A CARRIAGE-RETURN C2ECHS: CALLR ECHSTR ;;;ECHO STRING AND RETURN .SBTTL . I2CTU2 - SET UP TO ECHO PROMPT ; ; I2CTU2 - "^U " HAS BEEN ECHOED. SEE IF PROMPT BUFFER NEEDS ECHOING. ; I2CTU2:: ASSUME S1.USI,100000 TST (R5) ;;;ARE WE DOING UNSOLICITED INPUT? BPL I2CTR2 ;;;IF PL, NO...START PROMPT ECHO CLRB U.TFPB(R4) ;;;SET UP TO USE THE DEFAULT PROMPT TSTB U.TFPB+1(R4) ;;;DID THE UNSOLICITED INPUT INTERRUPT A READ? .IF DF T$$SER BNE 80$ ;;;IF NE, YES...DO NOT ECHO CLI PROMPT BIT #UM.CMD,U.MUP-U.TSTA(R5) ;;;IS A CLI COMMAND IN PROGRESS? .ENDC ;T$$SER BEQ I2CTR2 ;;;IF EQ, NO...START ECHOING THE PROMPT 80$: .IF DF R$$MPL!A$$CLI INCB U.TISV(R4) ;;;BYPASS CLI PROMPT OUTPUT STATE .ENDC ;R$$MPL!A$$CLI BR 60$ ;;;SKIP TO OUTPUT A CARRIAGE RETURN .SBTTL . I2CTR2 - SET UP TO ECHO PROMPT ; ; I2CTR2 - "^R " HAS BEEN ECHOED. INITIALIZE TO START OUTPUT OF THE ; CURRENT PROMPT BUFFER. THIS CODE IS ALSO ENTERED DURING CONTROL-U ; ECHO PROCESSING. ; I2CTR2:: INCB U.TISV(R4) ;;;UPDATE STATE VARIABLE ; ; RESET THE CURRENT HORIZONTAL POSITION TO THE INITIAL HORIZONTAL POSITION ; FOR THE READ PORTION OF AN IO.RPR. WE DON'T CARE ABOUT INCORRECT HORIZONTAL ; POSITION DURING THE ECHO OF THE PROMPT STRING. FURTHERMORE, IT IS POSSIBLE ; THAT THE ORIGINAL PROMPT STARTED AT A POSITION OTHER THAN FIRST COLUMN. IF ; SO, WE CAN ONLY HOPE THAT THE PROMPT BUFFER CONTAINS AN EXPLICIT CURSOR ; POSITIONING COMMAND. IF NOT, THE HORIZONTAL POSITION WILL BE INCORRECT ; WHILE DOING THE NEXT READ. ; ; AT THIS INPUT STATE, WE KNOW THAT THE LAST CHARACTER THAT WAS EXPANDED BY ; "EXPCHR" WAS A CARRIAGE RETURN, SO THE FORCE-LINE-FEED FLAG (S2.FLF) IS NOW ; SET. IF THE INITIAL HOR. POS. IS NOT COLUMN 1, WE MUST CLEAR THE FLAG. ; MOVB U.TIHP(R4),U.TCHP-U.TSTA(R5) ;;;RESET HORIZONTAL POSITION BEQ 90$ ;;;IF EQ, WE ARE AT COLUMN 1...LEAVE S2.FLF SET BIC #S2.FLF,2(R5) ;;;OTHERWISE, CLEAR FLAG TO PREVENT EXTRA LF 90$: .IF DF T$$RPR ASSUME S1.USI,100000 TST (R5) ;;;ARE WE DOING UNSOLICITED INPUT? BMI 100$ ;;;IF MI, YES...ECHO THE CLI PROMPT .IF DF R$$MPL!A$$CLI INCB U.TISV(R4) ;;;BYPASS CLI PROMPT OUTPUT STATE .ENDC ;R$$MPL!A$$CLI MOV U.TFPB(R4),U.TFOB(R4) ;;;GET THE FIRST PROMPT BUFFER CALLR STAXL ;;;START ECHO OF THE PROMPT STRING ; ; PREPARE FOR CLI PROMPT OUTPUT. ; 100$: .ENDC ;T$$RPR .IF DF T$$SPC TST U.TFPB(R4) ;;;CLI CONTINUATION LINE IN PROGRESS? BPL 110$ ;;;IF PL, NO...SKIP MOV #ASCLC,R3 ;;;OTHERWISE, OUTPUT SPECIAL CONTINUATION PROMPT MOV #4,R2 ;;;LENGTH IS 4 BYTES INCLUDING CR AND LF BR C2ECHS ;;;GO ECHO THE CONTINUATION STRING 110$: .ENDC ;T$$SPC .IF DF R$$MPL!A$$CLI MOV U.MUP-U.TSTA(R5),R3 ;;;GET POINTER TO CLI WORD BIC #^C,R3 ;;;CLEAR ALL BUT CLI INDEX MOV $CPTBL(R3),R3 ;;;POINT TO CLI PARSER BLOCK MOVB C.PDPL(R3),R2 ;;;GET DEFAULT PROMPT LENGTH ADD #C.PRMT,R3 ;;;POINT TO DEFAULT PROMPT STRING TSTB U.TFPB(R4) ;;;WHICH PROMPT DO WE ISSUE? BNE 120$ ;;;IF NE, SKIP TO ISSUE FULL CLI PROMPT TST R2 ;;;CHECK FOR NULL LENGTH BR 130$ ;;;EITHER PROMPT OR FORGET IT ALL 120$: MOVB C.PCPL-C.PRMT(R3),-(SP) ;;;GET LENGTH OF FULL CLI PROMPT ADD R2,R3 ;;;POINT TO FULL CLI PROMPT STRING MOVB (SP)+,R2 ;;;GET ITS LENGTH 130$: BEQ 140$ ;;;IF EQ, NULL LENGTH...DON'T PROMPT MOV R3,U.TSHP(R4) ;;;SAVE CLI PROMPT STRING ADDRESS MOVB R2,U.TVFC(R4) ;;;SAVE CLI PROMPT STRING LENGTH ;;;FALL INTO NEXT STATE .SBTTL . I2CTU3/I2CTR3 - OUTPUT CLI PROMPT BUFFER ; ; I2CTU3/I2CTR3 - OUTPUT CLI PROMPT BUFFER BY EXPANDING EACH CHARACTER IN TURN. ; I2CTU3:: I2CTR3:: MOV U.TSHP(R4),R3 ;;;GET ADDRESS OF NEXT CHARACTER MOVB U.TVFC(R4),R2 ;;;GET REMAINING LENGTH BNE 150$ ;;;IF NE, MORE TO DO...SKIP 140$: INCB U.TISV(R4) ;;;UPDATE STATE VARIABLE BR J2NXST ;;;GO TO NEXT STATE 150$: MOVB (R3)+,R2 ;;;GET CHARACTER TO EXPAND CALL EXPCHR ;;;GET CHARACTER EXPANSION BNE 160$ ;;;IF NE, CHARACTER ECHOES AS A STRING - SKIP MOV U.TSHP(R4),R3 ;;;SET POINTER TO CHARACTER MOV #1,R2 ;;;SET LENGTH BR 170$ ;;;UPDATE POINTER AND COUNT 160$: BCS 180$ ;;;IF CS, NEED TO PRESENT CHARACTER AGAIN 170$: INC U.TSHP(R4) ;;;POINT TO NEXT CHARACTER DECB U.TVFC(R4) ;;;KEEP COUNT 180$: BR C2ECHS ;;;ECHO EXPANSION OF CURRENT CHARACTER .IFF ;R$$MPL!A$$CLI MOV #ASCLP,R3 ;;;ASSUME ECHO ANGLE BRACKET ONLY MOV #2,R2 ;;;TWO BYTES LENGTH (INCLUDES LF) TSTB U.TFPB(R4) ;;;DID WE ASSUME CORRECTLY? BEQ C2ECHS ;;;IF EQ, YES...SKIP TO ECHO THE STRING .IF DF M$$CLI MOV U.CLI-U.TSTA(R5),R3 ;;;GET POINTER TO CLI TST (R3)+ ;;;POINT PAST CLI TCB MOV R3,R2 ;;;COPY POINTER TO CLI NAME 190$: TSTB (R2)+ ;;;SEARCH FOR END OF ASCIZ NAME AND PROMPT BNE 190$ ;;;IF NE, NOT THERE...LOOP SUB R3,R2 ;;;GET LENGTH OF CLI PROMPT BR C2ECHS ;;;ECHO CLI PROMPT .IFF ;M$$CLI MOV #ASCLI,R3 ;;;GET ADDRESS OF FULL CLI PROMPT MOV #5,R2 ;;;GET PROMPT LENGTH BR C2ECHS ;;;ECHO CLI PROMPT .ENDC ;M$$CLI .ENDC ;R$$MPL!A$$CLI .DSABL LSB .PAGE .SBTTL . I2CTU4 - FINISH CONTROL-U PROCESSING ; ; I2CTU4 - COMPLETE PROCESSING OF CONTROL-U INPUT. IF CONTROL-U WAS FOR ; AN UNSOLICITED INPUT, "IS.TMO+1" IS SET AS A COMPLETION STATUS SO ; THAT "FPIRD" WILL KNOW THE DIFFERENCE BETWEEN A USER HITTING ^U ; AND A FAKED ^U BECAUSE OF AN INPUT TIMEOUT. ; I2CTU4:: I2CTUE: CLRB U.TISV(R4) ;;;RESET THE INPUT STATE VARIABLE MOVB U.TCHP-U.TSTA(R5),U.TIHP(R4) ;;;SET INITIAL HOR. POS. = CURRENT ASSUME S1.USI,100000 TST (R5) ;;;ARE WE DOING UNSOLICITED INPUT? BPL C2CFRQ ;;;IF PL, NO...SKIP TO DO A FORK REQUEST ASSUME U.TCI,0 MOV #IS.TMO+1,@(R4)+ ;;;OTHERWISE, SHOW A TIMEOUT ^U HAS FINISHED JMP IDONE ;;;COMPLETE THE INPUT REQUEST .SBTTL . I2CTR4 - INITIATE ECHO OF CURRENT INPUT ; ; I2CTR4 - SET UP THE INPUT STATE TO RE-ECHO THE INPUT BUFFER. THIS IS DONE ; BY "RECYCLING" ALL CHARACTERS THAT HAVE BEEN INPUT SO FAR THROUGH ; THE INPUT LOGIC. ; I2CTR4:: INCB U.TISV(R4) ;;;UPDATE STATE VARIABLE .SBTTL . I2CTR5 - RECYCLE NEXT INPUT CHARACTER ; ; I2CTR5 - ECHO THE NEXT INPUT CHARACTER BY SENDING IT THROUGH THE INPUT LOGIC. ; I2CTR5:: MOV U.TIP+2(R4),R3 ;;;GET POINTER TO NEXT BYTE TO PROCESS CMP R3,U.TTOC(R4) ;;;ALL DONE? BEQ I2CTR6 ;;;IF EQ, YES...SKIP CALL GETRIC ;;;GET THE NEXT CHARACTER CALLR ICHAR2 ;;;RECYCLE CHARACTER THRU INPUT LOGIC .SBTTL . I2CTR6 - FINISH CONTROL-R PROCESSING ; ; I2CTR6 - COMPLETE PROCESSING OF CONTROL-R. RESET THE INPUT STATE AND ; CONDITIONALLY FORK TO START ANY PENDING OUTPUT REQUEST. ; I2CTR6:: CLRB U.TISV(R4) ;;;RESET THE INPUT STATE VARIABLE C2CFRQ: CALLR CFGRQ ;;;CONDITIONALLY FORK TO GET AN OUTPUT REQUEST .PAGE .SBTTL . I2CTC - CONTROL-C HANDLING ; ; I2CTC - CONTROL-C IS BEING PROCESSED. START (OR RESTART) UNSOLICITED INPUT. ; I2CTC:: .IF DF T$$SCA BIT #S3.TME,4(R5) ;;;IS TERMINAL MANAGEMENT ENABLED? BEQ 5$ ;;;IF EQ NO JMP I2ECHO ;;;IF NE, YES...DON'T DO CONTROL-C STUFF 5$: .ENDC ;T$$SCA ASSUME U2.SLV,200 TSTB U.CW2-U.TSTA(R5) ;;;SLAVED TERMINAL? BMI I2RET ;;;IF MI, YES...IGNORE THE CONTROL-C .IF DF T$$IDO TST $MCRPT ;;;IS THE MCR DISPATCHER INSTALLED? BNE 10$ ;;;IF NE, YES...SKIP ; ; THE FORK ROUTINE WHICH STARTS UNSOLICITED INPUT WILL QUEUE THE AST TO ; C$CTEX IF APPROPRIATE. MOV #FR.SUI,R3 ;;;FORK/START OF UNSOLICITED INPUT CALLR FORK ;;;QUEUE FORK REQUEST 10$: .ENDC ;T$$IDO .IF DF T$$SPC BIT #UM.KIL,U.MUP-U.TSTA(R5) ;;;SEND A KILL PACKET? BEQ 20$ ;;;IF EQ, NO...SKIP MOV #FR.KIL,R3 ;;;GET KILL FORK REQUEST BIT CALLR FORK ;;;REQUEST FORK TO KILL THIS INPUT 20$: TST U.TFPB(R4) ;;;CLI CONTINUATION LINE IN PROGRESS? BPL 30$ ;;;IF PL, NO...SKIP BIS #UM.KIL,U.MUP-U.TSTA(R5) ;;;ELSE, SEND KILL PACKET ON NEXT ^C 30$: .ENDC ;T$$SPC MOVB R2,U.TFPB(R4) ;;;ECHO A FULL CLI PROMPT FOR ^U/^R ADD #U.TFIB,R4 ;;;POINT TO U.TFIB MOV R1,-(SP) ;;;SAVE REGISTER CALL FPSUI1 ;;;SET UP UCB FOR UNSOLICITED INPUT ; ; FILL THE INPUT BUFFER WITH THE FOLLOWING PROMPT STRING: ; " \ XXX>" ; ; WHERE " \" TAKES THE TERMINAL OUT OF HOLD-SCREEN MODE (INSERTED ; ONLY IF TERMINAL IS IN HOLD-SCREEN MODE); AND "XXX" IS THE CLI NAME. ; ASSUME U.TIP+2,U.TIC-2 MOV -(R4),R1 ;;;GET START OF THE OUTPUT BUFFER BIT #U2.HLD,U.CW2-U.TSTA(R5) ;;;IN HOLD-SCREEN MODE? BEQ 40$ ;;;IF EQ, NO...SKIP MOV (PC)+,(R1)+ ;;;INSERT \ - EXIT HOLD SCREEN MODE .BYTE CH.ESC,CH.BSL BIC #U2.HLD,U.CW2-U.TSTA(R5) ;;;CLEAR HOLD-SCREEN FLAG 40$: ; ; NOW EXPAND CARRIAGE RETURN TWICE. THIS HAS THE FOLLOWING EFFECT: ; 1. IF THE LAST EXPANDED CHARACTER WAS NOT A CARRIAGE RETURN, ; THE FIRST CR EXPANDS AS CR, AND THE SECOND ONE AS LF. ; 2. ELSE, THE FIRST CR EXPANDS AS LF AND THE SECOND ONE AS CR. ; IN THIS CASE, THE FLAG S2.FLF WILL BE SET AFTER THE SECOND ; EXPANSION AND MUST BE CLEARED. ; ; THE CARRIAGE RETURN AND LINE FEED ARE NOT OUTPUT HERE FOR ALTERNATE CLI ; SYSTEMS SINCE THE CLI MAY NOT WANT THEM. IF IT DOES, THEN THEY MUST BE ; PART OF THE CLI PROMPT STRING IN THE CPB. ; .IF DF T$$SPC TST U.TFPB-(R4) ;;;CLI CONTINUATION LINE IN PROGRESS? BPL 70$ ;;;IF PL, NO...DON'T INCLUDE GRATIS CRLF .ENDC ;T$$SPC .IIF NDF A$$CLI,NOACLI=0 .IF DF T$$SPC!NOACLI CALL EXCR1 ;;;EXPAND A CARRIAGE RETURN 50$: MOVB (R3)+,(R1)+ ;;;INSERT SOB R2,50$ ;;;LOOP CALL EXCR1 ;;;EXPAND CR AGAIN 60$: MOVB (R3)+,(R1)+ ;;;INSERT SOB R2,60$ ;;;LOOP .ENDC ;T$$SPC!NOACLI 70$: BIC #S2.FLF,2(R5) ;;;DON'T FORCE ANOTHER LF .IF DF T$$SPC TST U.TFPB-(R4) ;;;CLI CONTINUATION LINE IN PROGRESS? BPL 90$ ;;;IF PL, NO...SKIP MOVB ASCLC+2,(R1)+ ;;;INSERT FIRST CHAR. OF CONTINUATION PROMPT MOVB ASCLC+3,(R1)+ ;;;INSERT SECOND CHAR. OF PROMPT MOVB #2,U.TCHP-U.TSTA(R5) ;;;SET UP CURRENT HOR. POS. MOVB #2,U.TIHP-(R4) ;;;SET INITIAL HOR. POS. BR 170$ ;;;OUTPUT THE PROMPT .ENDC ;T$$SPC .IF DF M$$CLI MOV U.CLI-U.TSTA(R5),R3 ;;;GET POINTER TO CLI NAME ADD #4,R3 ;;;ADD IN LENGTH OF THE CLI NAME 80$: MOVB (R3)+,(R1)+ ;;;INSERT BNE 80$ ;;;LOOP .ENDC ;M$$CLI .IF DF R$$MPL!A$$CLI 90$: MOV U.MUP-U.TSTA(R5),R3 ;;;GET POINTER TO CLI STATUS WORD BIC #^C,R3 ;;;CLEAR ALL BUT CLI INDEX BITS MOV $CPTBL(R3),R3 ;;;POINT TO CLI PARSER BLOCK ADD #C.PDPL,R3 ;;;POINT TO DEFAULT PROMPT STRING LENGTH ASSUME C.PCPL,C.PDPL+1 CLR -(SP) ;;;WORD TO GET BYTE VALUE OF PROMPT LENGTH BISB (R3)+,(SP) ;;;GET LENGTH OF DEFAULT PROMPT ASSUME C.PRMT,C.PCPL+1 MOVB (R3)+,R2 ;;;GET LENGTH OF CLI PROMPT ADD (SP)+,R3 ;;;POINT TO CLI PROMPT STRING TST R2 ;;;ANYTHING THERE? BEQ I2RET ;;;IF EQ, NO...RETURN TO FORGET IT ALL MOV R1,-(SP) ;;;GET CURRENT POSITION IN OUTPUT BUFFER SUB (R4),(SP) ;;;GET NUMBER OF CHARACTERS IN IT SO FAR MOV R2,-(SP) ;;;SAVE UNEXPANDED CLI PROMPT LENGTH 100$: MOVB (R3)+,R2 ;;;GET A CHARACTER OF THE PROMPT MOV R3,-(SP) ;;;SAVE ADDRESS OF NEXT CHARACTER CALL EXPCHR ;;;GET EXPANSION OF CURRENT CHARACTER BNE 120$ ;;;IF NE, IT IS A STRING...SKIP CMP 4(SP),#T$$BFL ;;;BUFFER LENGTH EXCEEDED? BHIS 110$ ;;;IF HIS, YES...SKIP MOVB R2,(R1)+ ;;;CHARACTER EXPANDS AS ITSELF - PUT IN BUFFER INC 4(SP) ;;;SHOW ONE MORE CHARACTER IN BUFFER BR 150$ ;;;CHECK IF DONE 110$: ADD #6,SP ;;;CLEAN STACK BR 170$ ;;;ECHO WHATEVER COULD FIT IN THE BUFFER 120$: BCC 130$ ;;;IF CC, DON'T PRESENT CHARACTER AGAIN...SKIP DEC (SP) ;;;ELSE, BACKUP POINTER INC 2(SP) ;;;AND FIX COUNT 130$: ADD R2,4(SP) ;;;SHOW NEW BUFFER LENGTH CMP 4(SP),#T$$BFL ;;;BUFFER LENGTH EXCEEDED? BHI 110$ ;;;IF HI, YES...ECHO WHAT WE COULD COPY 140$: MOVB (R3)+,(R1)+ ;;;PUT EXPANSION INTO BUFFER SOB R2,140$ ;;;LOOP 150$: MOV (SP)+,R3 ;;;RESTORE PROMPT POINTER DEC (SP) ;;;MORE TO DO? BNE 100$ ;;;IF NE, YES...LOOP UNTIL DONE 160$: CMP (SP)+,(SP)+ ;;;CLEAN STACK .ENDC ;R$$MPL!A$$CLI .IF NDF R$$MPL&A$$CLI&M$$CLI MOVB #'M,(R1)+ ;;;INSERT M MOVB #'C,(R1)+ ;;; C MOVB #'R,(R1)+ ;;; R MOVB #'>,(R1)+ ;;; > .ENDC ;NDF R$$MPL&A$$CLI&M$$CLI .IF NDF R$$MPL&A$$CLI MOVB #4,U.TCHP-U.TSTA(R5) ;;;SET UP CURRENT HOR. POS. MOVB #4,U.TIHP-(R4) ;;;SET INITIAL HOR. POS. .ENDC ;NDF R$$MPL&A$$CLI 170$: MOV (R4),R3 ;;;GET START OF PROMPT STRING (U.TIP+2) CMP -(R4),-(R4) ;;;RESTORE UCBX POINTER MOV R1,R2 ;;;COPY CURRENT PROMPT STRING POINTER SUB R3,R2 ;;;GET LENGTH OF THE STRING MOV (SP)+,R1 ;;;RESTORE REGISTER BIC #U2.HLD,U.CW2-U.TSTA(R5) ;;;CLEAR HOLD-SCREEN FLAG ECHOS1: CALLR ECHSTR ;;;ECHO THE PROMPT STRING .PAGE .SBTTL . I2CT* - MISCELLANEOUS CONTROL CHARACTER HANDLING ; ; CTRL-Q, CTRL-S, CTRL-O AND CTRL-X. ; IF ANY OF THESE CHARACTERS IS RECEIVED WHEN AN IO.RAL OR IO.RST ; IS ACTIVE, STORED IN THE TYPE-AHEAD BUFFER (FOR EXAMPLE, BECAUSE ; ECHO IS REQUIRED AND OUTPUT IS BUSY), THE READ TERMINATES AND ; THE NEXT READ IS AN IO.RLB, THEN THESE SPECIAL CHARACTERS WILL ; APPEAR HERE. WE DON'T WANT TO PASS THEM TO THE TASK, SO WE ; JUST IGNORE THEM. ; ; THE SAME IS DONE FOR CTRL-C FROM A SLAVED TERMINAL, AND FOR CTRL-R ; IN A SYSTEM THAT DOES NOT SUPPORT CTRL-R. ; I2CTQ:: I2CTS:: BIT #S1.TSY,(R5) ;IS TERMINAL SYNC ENABLED? BEQ JI2EC ;IF NE, YES,KEEP CHARACTER I2CTX:: I2CTO:: .IF NDF T$$CTR EDCTR:: .ENDC ;T$$CTR I2RET: RETURN ;;;IGNORE JI2EC: JMP I2ECHO ;;;ELSE, PROCESS AS A NORMAL INPUT CHARACTER .PAGE .SBTTL . EDRUB - RUBOUT CHARACTER HANDLING ; ; EDRUB - PROCESS RUBOUT CHARACTER. ; EDRUB:: CALL GETPIC ;;;GET (AND REMOVE) PREVIOUS CHARACTER BCS I2RET ;;;IF CS, NONE THERE...IGNORE RUBOUT BIT #S1.RNE,(R5) ;;;IS ECHO SUPPRESSED? BNE I2RET ;;;IF NE, YES...DON'T ECHO DELETED CHARACTER TSTB U.TCHP-U.TSTA(R5) ;;;AT LEFT MARGIN? BEQ I2RET ;;;IF EQ, YES...CAN'T ECHO AROUND WRAP .IF DF T$$RUB BIT #U2.CRT,U.CW2-U.TSTA(R5) ;;;IS TERMINAL A SCOPE? BEQ 70$ ;;;IF EQ, NO...START RUBOUT SEQUENCE ; ; ECHO THE STANDARD CRT RUBOUT SEQUENCE. HORIZONTAL TAB ECHOS AS A NUMBER ; (1-8) OF BACKSPACES. ANYTHING ELSE ECHOS AS BACKSPACE-SPACE-BACKSPACE. ; CMPB R2,#CH.HT ;;;RUBOUT HORIZONTAL TAB? BEQ 10$ ;;;IF EQ, YES...SKIP BITB #140,R2 ;;;NON-SPACING CHARACTER? BEQ I2RET ;;;IF EQ, YES...DELETE IT BUT DON'T ECHO MOV #ASRBS,R3 ;;;POINT TO BSP-SP-BSP STRING MOV #3,R2 ;;;SET LENGTH OF STRING DECB U.TCHP-U.TSTA(R5) ;;;UPDATE CURRENT HORIZONTAL POSITION BR ECHOS1 ;;;GO ECHO THE STRING ; ; FIND THE PREVIOUS HORIZONTAL POSITION. ; 10$: MOVB U.TCHP-U.TSTA(R5),-(SP) ;;;SAVE CURRENT HORIZONTAL POSITION MOVB U.TIHP(R4),U.TCHP-U.TSTA(R5) ;;;RESET CURRENT TO INITIAL POS. MOV R3,-(SP) ;;;SAVE R3 (POINTS TO THE HTAB) ASSUME U.TCI,0 MOV (R4),R3 ;;;GET CURRENT PACKET (IF SOLICITED INPUT) MOV I.PRM+2(R3),R3 ;;;GET START OF TASK BUFFER ; ; NOTE - THE 2 INSTRUCTIONS ABOVE ASSUME THAT THE CURRENT INPUT IS UNBUFFERED ; SOLICITED INPUT. OF COURSE, "I.PRM+2(R3)" MAKES NO SENSE IF THE INPUT IS ; UNSOLICITED, BUT NO ADDRESSING ERROR CAN OCCUR. ; CLR -(SP) ;;;SET UP A VERY LARGE LOOP COUNT BIT #S1.IBF,(R5) ;;;ARE WE DOING BUFFERED INPUT? BEQ 30$ ;;;IF EQ, NO...SKIP TO EXPAND BUFFER MOV U.TFIB(R4),R3 ;;;GET FIRST INPUT BUFFER 20$: CMP (R3)+,(R3)+ ;;;POINT TO START OF DATA AREA MOV #T$$BFL-4,(SP) ;;;SET MAX BYTES IN BUFFER ; ; THE FOLLOWING IS A LOOP THAT GOES THROUGH ALL CHARACTERS THAT HAVE BEEN ; INPUT SO FAR AND EXPANDS THEM. THE PURPOSE IS TO UPDATE THE CURRENT ; HORIZONTAL POSITION (U.TCHP) TO THE VALUE IT HAD BEFORE THE LAST ; CHARACTER (THE TAB) WAS INPUT. ; 30$: CMP R3,2(SP) ;;;POINTING TO THE RUBBED-OUT CHARACTER? BEQ 50$ ;;;IF EQ, YES...WE ARE DONE 40$: CALL GETRIC ;;;GET THE CHARACTER POINTED TO BY R3 MOV R3,-(SP) ;;;SAVE R3 CALL EXPCHR ;;;EXPAND THE CHARACTER MOV (SP)+,R3 ;;;RESTORE R3 BCS 40$ ;;;IF CS, EXPAND CHARACTER AGAIN (DEFERRED ECHO) INC R3 ;;;UPDATE POINTER DEC (SP) ;;;DECREMENT LOOP COUNT BNE 30$ ;;;IF NE, MORE IN THIS BUFFER...LOOP FOR MORE MOV -T$$BFL(R3),R3 ;;;LOOP COUNT RAN OUT - THIS CAN ONLY HAPPEN... ;;; ...IF WE ARE DOING BUFFERED INPUT, SO... ;;; ...GET LINK TO NEXT BUFFER (MUST BE ONE) BR 20$ ;;;BIG LOOP ; ; WE ARE BACK AT WHERE WE STARTED - U.TCHP CONTAINS NEW (BACKSPACED) ; HORIZONTAL POSITION. ; 50$: CMP (SP)+,(SP)+ ;;;CLEAN STACK MOV (SP),R2 ;;;GET OLD HORIZONTAL POSITION MOVB U.TCHP-U.TSTA(R5),(SP) ;;;GET NEW HORIZONTAL POSITION SUB (SP)+,R2 ;;;CALCULATE NUMBER OF BACKSPACES REQUIRED BGT 60$ ;;;IF GT, OUTPUT THEM MOV #8.,R2 ;;;THE TAB WE WANT TO RUB OUT CAUSED AN... ;;; ...AUTO CR-LF - SPACE BACK TO LEFT MARGIN 60$: MOV #ASBSP,R3 ;;;POINT TO STRING WITH BACKSPACES BR ECHOS1 ;;;ECHO THE STRING .ENDC ;T$$RUB ; ; PROCESS A RUBOUT FOR A HARDCOPY TERMINAL. THE ECHO SEQUENCE STARTS WITH ; A BACKSLASH FOLLOWED BY EACH CHARACTER THAT IS RUBBED OUT. WHEN NO MORE ; CHARACTERS ARE TO BE RUBBED OUT, A TERMINATING BACKSLASH IS ECHOED FOLLOWED ; BY THE CHARACTER THAT TERMINATED THE RUBOUT PROCESS. ; 70$: .IF DF T$$SPL MOVB R2,U.TECO-U.TSTA(R5) ;;;SAVE RUBBED-OUT CHARACTER .IFF ;T$$SPL MOVB R2,U.TECB(R4) ;;;SAVE RUBBED-OUT CHARACTER .ENDC ;T$$SPL BIT #S3.RUB,4(R5) ;;;ALREADY IN RUBOUT SEQUENCE? BNE 80$ ;;;IF NE, YES...ECHO RUBBED-OUT CHARACTER BIS #S1.DEC,(R5) ;;;SET RUBOUT AND DEFERRED ECHO FLAGS BIS #S3.RUB,4(R5) BR I2RUB2 ;;;SKIP TO ECHO A BACKSLASH FIRST 80$: CALLR I2EXPC ;;;EXPAND & ECHO CHAR. IN R2 & U.TECB (U.TECO) ; ; I2RUB1 - WE ARE ALREADY IN RUBOUT MODE. ; I2RUB1: CMPB R2,#CH.RUB ;;;IS THIS ALSO A RUBOUT? BEQ EDRUB ;;;IF EQ, YES...CONTINUE RUBOUT SEQUENCE BIC #S3.RUB,4(R5) ;;;ELSE, GET OUT OF RUBOUT MODE BIS #S1.DPR,(R5) ;;;SET DEFERRED PROCESSING FLAG ;;;FALL THROUGH TO ECHO A TERMINATING BACKSLASH ; ; I2RUB2 - OUTPUT LEADING OR TRAILING BACKSLASH FOR HARDCOPY RUBOUT SEQUENCE. ; I2RUB2: MOV #ASBSL,R3 ;;;POINT TO BACKSLASH CHARACTER TO OUTPUT INCB U.TCHP-U.TSTA(R5) ;;;UPDATE HORIZONTAL POSITION CALLR ECHCHR ;;;ECHO 1 CHARACTER POINTED TO BY R3 .PAGE .SBTTL TTICH SUBROUTINES .SBTTL . SETSPD - FIND AND SET THE CALLER'S BAUD RATE ; ;+ ; SETSPD - DETERMINE THE INCOMING CALLER'S BAUD RATE AND SET IT. ; ; INPUTS: ; R2 = CHARACTER RECEIVED ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; R2 = IF THE LINE SPEED IS FOUND AND SET UP ; = 0 IF THE LINE SPEED COULD NOT BE DETERMINED ; THE CONTROLLER DEPENDENT ROUTINE FOR SETTING THE LINE SPEED IS ; CALLED AS EACH RANGE OF LINE SPEEDS IS CHECKED. ; ; REGISTERS MODIFIED: R3, R4 (BY CONTROLLER DEPENDENT ROUTINES) ;- ; .IF DF D$$M11!D$$ZMD!D$$VMD SETSPD: CLR -(SP) ;;;SET UP RETURN VALUE FOR R2 = SPEED NOT FOUND MOV R1,-(SP) ;;;SAVE REGISTERS USED BY THIS ROUTINE MOV R0,-(SP) ;;; MOV U.CW4-U.TSTA(R5),R0 ;;;GET THE CURRENT SPEED AND FLAGS WORD BIC #^C<37>,R0 ;;;CLEAR ALL BUT SPEED BITS BIC #^C<377>,R2 ;;;CLEAR ALL BUT EIGHT BITS OF INPUT CHARACTER CMPB R2,#CH.CR ;;;IS IT A CARRIAGE RETURN (SPEED IS CORRECT)? BEQ 60$ ;;;IF EQ, YES...EXIT AUTOBAUD STATE CMPB R2,# ;;;8-BIT CARRIAGE RETURN (SPEED IS CORRECT)? BEQ 60$ ;;;IF EQ, YES...EXIT AUTOBAUD STATE BIT #U4.CR,U.CW4-U.TSTA(R5) ;;;EXPECTING TO SEE A CARRIAGE RETURN? BNE 20$ ;;;IF NE, YES...WE DIDN'T GET ONE, SO LOG IT CMPB R0,#S.4800 ;;;DID WE JUST FINISH SEARCHING AT 4800 BAUD? BNE 10$ ;;;IF NE, NO...GO SEARCH LOW BAUD RATE TABLE NOW TST R2 ;;;WAS RECEIVED CHARACTER A NULL? BNE 30$ ;;;IF NE, NO...SEARCH HIGH BAUD RATE TABLE NOW MOV #S.300,R0 ;;;SEARCH THE LOW BAUD SPEED RANGE NEXT TIME BR 50$ ;;;CHANGE THE SPEED AND WAIT FOR NEXT CHARACTER ; ; THE PREVIOUS INPUT CHARACTER DID NOT MATCH ANYTHING IN THE HIGH BAUD RATE ; RANGE. WE HAVE A NEW CHARACTER TO CHECK AGAINST THE LOW BAUD RATE TABLE NOW. ; 10$: MOV #ABLOW,R1 ;;;SET ADDRESS OF LOW BAUD SPEED TABLE CALL TBLCHK ;;;LOOK FOR A MATCH AGAINST RECEIVED CHARACTER BEQ 40$ ;;;IF CC, FOUND MATCH...SET SPEED FROM TABLE ; ; WE COME HERE IN EITHER OF THE FOLLOWING CASES: ; 1. AN INPUT CHARACTER COULD NOT BE MATCHED WITH THE HIGH BAUD RATE ; TABLE ENTRIES; THE LINE SPEED WAS CHANGED FOR LOW SPEED CHECKING; ; AND THE NEXT CHARACTER DID NOT MATCH THE LOW BAUD RATE TABLE. ; 2. A MATCH WAS FOUND IN EITHER THE LOW OR HIGH SPEED TABLE, AND THE ; NEXT CHARACTER WAS EXPECTED TO BE A CARRIAGE RETURN (FOR ; VALIDATION). HOWEVER, IT WASN'T A CARRIAGE RETURN. ; 20$: INCB U.CW4+1-U.TSTA(R5) ;;;INCREMENT ERROR COUNT CMPB U.CW4+1-U.TSTA(R5),#5 ;;;REACHED THRESHOLD? BLT 70$ ;;;IF LT, NO...KEEP PRESENT SPEED MOV #S.4800,R0 ;;;RESET SPEED, ERROR COUNT AND FLAGS BR 50$ ;;;TRY AGAIN WITH ORIGINAL RANGE CHECK ; ; SEARCH THE HIGH BAUD RATE TABLE FOR A MATCH WITH THE CURRENT INPUT CHARACTER. ; 30$: MOV #ABHIGH,R1 ;;;SET ADDRESS OF HIGH BAUD SPEED TABLE CALL TBLCHK ;;;LOOK FOR A MATCH AGAINST RECEIVED CHARACTER BNE 70$ ;;;IF NE, NO MATCH...KEEP PRESENT SPEED ; ; FOUND A MATCHING CHARACTER IN SPEED TABLE. SET SPEED FROM THE TABLE AND ; LOOK FOR A REAL CARRIAGE RETURN AS THE NEXT INPUT CHARACTER. ; 40$: MOVB (R1)+,R0 ;;;GET CALLER'S SPEED FROM TABLE BIS #U4.CR,R0 ;;;VALIDATE THIS SPEED ON NEXT INPUT CHARACTER ; ; SET THE LINE TO A NEW LINE SPEED AS SPECIFIED BY R0. ; 50$: MOV R0,U.CW4-U.TSTA(R5) ;;;SET NEW SPEED VALUE AND FLAGS BR 70$ ;;;SET UP CONTROLLER AND WAIT FOR NEXT INPUT ; ; SINCE WE JUST RECOGNIZED A REAL CARRIAGE RETURN AS THE INPUT CHARACTER, ; WE ARE NOW AT THE CORRECT SPEED. EXIT AUTOBAUD-IN-PROGRESS MODE AND ; SET UP TO PROCESS THE CARRIAGE RETURN WHICH WILL GIVE A CLI PROMPT. ; 60$: BIC #S5.ABP,U.TST5-U.TSTA(R5) ;;;CLEAR AUTO-BAUD IN PROGRESS BIT MOV #80.,U.CW4-U.TSTA(R5) ;;;RESET CORRECT BUFFER WIDTH MOV R2,4(SP) ;;;SAVE CARRIAGE RETURN WE JUST DETECTED ; ; CALL THE CONTROLLER DEPENDENT ROUTINE TO SET THE LINE TO THE SPECIFIED SPEED. ; 70$: BIC #^C<37>,R0 ;;;CLEAR ALL BUT SPEED BITS BIS #4000,R0 ;;;SET AUTO-BAUD DETECT BIT FOR SET SPEED MOV #CT.PRM,R2 ;;;SET INDEX FOR CHANGING LINE PARAMETER CLR R1 ;;;SET FLAG FOR NOT FLOW-CONTROL CHANGE CALL CTRD ;;;GO CHANGE THE LINE SPEED MOV (SP)+,R0 ;;;RESTORE SAVED REGISTERS MOV (SP)+,R1 ;;; MOV (SP)+,R2 ;;;GET BACK RETURN STATUS (EITHER OR 0) RETURN ;;;ALL DONE ; ; TBLCHK - CHECK CURRENT SPEED TABLE FOR A MATCHING INPUT CHARACTER. ; TBLCHK: CMPB R2,(R1)+ ;;;RECEIVED CHARACTER MATCH TABLE ENTRY? BEQ 10$ ;;;IF EQ, YES...RETURN WITH ENTRY INC R1 ;;;BUMP PAST SPEED TSTB (R1) ;;;END OF THE TABLE? BNE TBLCHK ;;;IF NE, NO...KEEP LOOKING CLZ ;;;SHOW NO MATCH WAS FOUND 10$: RETURN ;;;DONE WITH SCAN .ENDC ;D$$M11!D$$ZMD!D$$VMD .PAGE .SBTTL . TMMCHK - CHECK FOR SWITCH TO TERMINAL MANAGEMENT MODE ; ; **-TMMCHK - CHECK FOR POSSIBLE SWITCH TO TERMINAL MANAGEMENT MODE ; ; THIS ROUTINE CHECKS THE CURRENT INPUT STATE AND THE CURRENT INPUT CHARACTER ; TO SEE IF A SWITCH TO TERMINAL MANAGEMENT MODE IS NECESSARY. ONE OF THE ; FOLLOWING ACTIONS IS PERFORMED (IN DECREASING PRIORITY): ; ; 1. IF TERMINAL MANAGEMENT MODE IS NOT ENABLED, JUST EXIT. ; 2. IF WE HAVE NOT SEEN THE FIRST SWITCH CHARACTER, SEE IF THE CURRENT ; INPUT CHARACTER IS IT. IF SO, UPDATE THE TERMINAL MANAGEMENT ; STATE FLAGS AND EXIT. ; 3. IF WE HAVE ALREADY SEEN THE FIRST SWITCH CHARACTER, SEE IF THE ; CURRENT INPUT CHARACTER IS THE FINAL ONE. IF SO, CLEAR ; THE TYPE-AHEAD BUFFER AND REQUEST A FORK TO SWITCH INTO ; TERMINAL MANAGEMENT MODE. ; 4. OTHERWISE, SAVE THE CURRENT INPUT CHARACTER, RECYCLE THE FIRST ; SWITCH CHARACTER THROUGH THE INPUT LOGIC, AND EXIT. IF THE ; USER ENTERED THE FIRST SWITCH CHARACTER TWICE, ONLY ONE OF ; THEM IS PASSED BACK TO THE INPUT LOGIC. ; ; INPUTS: ; R2 = CURRENT INPUT CHARACTER ; R5 => U.TSTA OF THE TERMINAL UCB ; U.TSCA => AST CONTROL BLOCK/TSA EVENT PACKET IF TMM IS ENABLED ; S5.SW1/S5.TMM = CURRENT TERMINAL MANAGEMENT STATE ; ; OUTPUTS: ; CC-C = 0 IF INPUT CHARACTER WAS NOT A SWITCH CHARACTER AND MUST BE ; PROCESSED UPON EXIT. ; CC-C = 1 IF INPUT CHARACTER WAS ONE OF THE SWITCH CHARACTERS AND ; SHOULD BE IGNORED UPON EXIT. ; ; REGISTERS MODIFIED: R3, R4 ;- ; .IF DF T$$SCA TMMCHK: .IF DF T$$SPL MOV 120000+U.TSCA,R4 ;;;GET SWITCH CHARACTER TEP/ACB .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET TERMINAL'S UCBX BEQ 40$ ;;;IF EQ, NO UCBX...SKIP SWITCH CHARACTER CHECK MOV U.TSCA(R4),R4 ;;;GET SWITCH CHARACTER ACB/TEP .ENDC ;T$$SPL BEQ 40$ ;;;IF EQ, NO SWITCH CHARACTERS SET UP...SKIP BIT #S5.TMM,U.TST5-U.TSTA(R5) ;;;ALREADY IN TERMINAL MGMT MODE? BNE 40$ ;;;IF NE, YES...SKIP SWITCH CHARACTER CHECKING MOV A.PRM+6(R4),R3 ;;;GET USER-DEFINED SWITCH CHARACTERS BIT #S5.SW1,U.TST5-U.TSTA(R5) ;;;ALREADY SEEN 1ST SWITCH CHARACTER? BEQ 10$ ;;;IF EQ, NO...CHECK FOR IT NOW SWAB R3 ;;;SWAP CHARACTERS TO CHECK FOR 2ND ONE 10$: CMPB R2,R3 ;;;DOES THIS SWITCH CHARACTER MATCH? BNE 30$ ;;;IF NE, NO...NO SWITCH TO TERM MGMT MODE ASSUME S5.SW1,1 ASSUME S5.TMM,S5.SW1+1 INC U.TST5-U.TSTA(R5) ;;;UPDATE SWITCH CHARACTER STATE BITS BIT #S5.TMM,U.TST5-U.TSTA(R5) ;;;SEEN 2ND SWITCH CHARACTER? BEQ 20$ ;;;IF EQ, NO...WAIT FOR NEXT CHARACTER ; ; FORK TO PUT USER IN TERMINAL MANAGEMENT MODE. ; CALL I1CTX1 ;;;GO FLUSH THE TYPE-AHEAD BUFFER CALL I1CTQ ;;;ALSO RESTART OUTPUT MOV #FR.SCA,R3 ;;;REQUEST FORK FOR SWITCH TO TERM MGMT MODE CALL FORK ;;;DO IT 20$: SEC ;;;INDICATE SWITCH CHARACTER WAS SEEN RETURN ;;;ALL DONE ; ; INPUT IS NOT A SWITCH CHARACTER - SEE IF NEED TO RECYCLE PREVIOUS CHARACTER. ; 30$: BIT #S5.SW1,U.TST5-U.TSTA(R5) ;;;DID WE SEE 1ST SWITCH CHARACTER? BEQ 40$ ;;;IF EQ, NO...JUST PROCESS CURRENT CHARACTER ASSUME S5.SW1,1 DEC U.TST5-U.TSTA(R5) ;;;CLEAR FLAG SAYING WE SAW 1ST ONE SWAB R3 ;;;SWAP TO GET 1ST SWITCH CHARACTER BACK CMPB R2,R3 ;;;DID USER ENTER 1ST SWITCH CHAR. TWICE? BEQ 40$ ;;;IF EQ, YES...JUST PASS ONE OF THEM THROUGH MOV R2,-(SP) ;;;SAVE CURRENT CHARACTER MOV 2(SP),-(SP) ;;;DUPLICATE RETURN ADDRESS FOR LATER CLR R2 ;;;PREPARE FOR BYTE COPY (AND CLEAR CC-C) BISB R3,R2 ;;;GET 1ST SWITCH CHARACTER BACK CALL @(SP)+ ;;;FEED IT THROUGH INPUT PROCESSING MOVB (SP)+,R2 ;;;GET BACK CURRENT CHARACTER 40$: CLC ;;;CLEAR RETURN STATUS RETURN ;;;RETURN TO FEED IT THROUGH THE INPUT PROCESS .ENDC ;T$$SCA .PAGE .SBTTL . OOBCHK - CHECK OUT-OF-BAND MASKS FOR INPUT CHARACTER ; ;+ ; **-OOBCHK - DETERMINE IF CURRENT INPUT CHARACTER IS OUT-OF-BAND ; ; ; INPUTS: ; R2 = CHARACTER ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; CC-C = 0 IF CHARACTER IS NOT OOB ; = 1 IF CHARACTER IS OOB ; ; REGISTERS ALTERED: R0, R3, R4 ;- ; ;- ; .IF DF T$$OOB .ENABL LSB OOBCHK: CLR R4 ;;;ASSUME NOT OOB CMPB R2,#CH.SP ;;;IS INPUT A CONTROL CHARACTER? BHIS 60$ ;;;IF HIS, NO...NOT SUPPORTED AS OOB .IF DF T$$SPL MOV 120000+U.TOBA,R3 ;;;GET OUT-OF-BAND ACB/TEP POINTER .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R3 ;;;GET UCBX POINTER BEQ 60$ ;;;IF EQ, NOT ONE...CAN'T BE OOB SO SKIP MOV U.TOBA(R3),R3 ;;;GET OUT-OF-BAND ACB/TEP POINTER .ENDC ;T$$SPL BEQ 60$ ;;;IF EQ, OUT-OF-BAND NOT SET UP...SKIP MOV R3,R4 ;;;COPY ACB/TEP POINTER ADD #A.PRM+6,R4 ;;;POINT TO START OF OOB BITMASKS ;;;ASSUME THIS IS AN ACB, NOT TEP .IF DF R$$IIC ASSUME A.CBL,E.VSIZ TST A.CBL(R3) ;;;ACB OR TEP? BEQ 5$ ;;;IF EQ, ACB .IF DF T$$SCA BIT #S5.TMM,U.TST5-U.TSTA(R5) ;;;IS USER IN TERMINAL MGMT MODE? BNE 12$ ;;;IF NE, YES... DON'T DO OOB CHECKS .ENDC ;T$$SCA ASSUME E.VOBM,A.PRM+2 ;;;NOTE: THIS CODE ALSO ASSUMES THAT THE ;;;OOB BITMASKS START AT A.PRM+6 SUB #4,R4 ;;;POINT TO ACB OOB BITMASKS 5$: .ENDC ;R$$IIC MOV R2,R0 ;;;COPY THE CHARACTER CMPB #16.,R0 ;;;IS CHARACTER IN FIRST MASK WORD? BHI 10$ ;;;IF HIS, YES...SKIP TO CHECK IT SUB #16.,R0 ;;;MAKE CHARACTER RELATIVE TO 16. TST (R4)+ ;;;POINT TO SECOND HALF OF DOUBLEWORD MASK 10$: ASL R0 ;;;CONVERT CHARACTER FOR WORD OFFSET BIT $BTMSK(R0),(R4)+ ;;;IS CHARACTER IN THE BITMASK? BNE 60$ ;;;IF NE, OOB 12$: CLR R4 ;;;INDICATE NOT OOB BR 60$ ;;;DONE ;+ ; **-OOBCK2 - DETERMINE WHETHER AN OOB CHARACTER IS INCLUDE AND ; PROCESS OOB CHARACTER BY INSERTING IT IN OOB BUFFER. ; IF THERE'S NO ROOM IN THE BUFFER, GO DIRECTLY TO ; WARN THE USER. OTHERWISE, CHECK FOR CLEAR AND ; PERFORM ASSOCIATED FUNCTION. SET STATUS AND SET UP ; FORK FOR OOB. ; ; NOTE: THIS ROUTINE IS DESIGNED TO BE CALLED IMMEDIATELY AFTER ; OOBCHK AND SHOULD BE CALLED ONLY IF THE CHAR. IS OOB. ; VALUES FOR R0, R3 AND R4 (INPUT TO OOBCK2) ARE ESTABLISHED ; BY CALLING OOBCHK. ALSO NOTE THAT IT IS ASSUMED THAT R0 ; WAS SAVED ON THE STACK PRIOR TO CALLING THIS ROUTINE. ; ; INPUTS: ; R0 ESTABLISHED BY OOBCHK ; R2 = CHARACTER ; R3 ESTABLISHED BY OOBCHK ; R4 ESTABLISHED BY OOBCHK ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; CC-C = 0 IF CHARACTER IT NOT TO BE INCLUDED ; = 1 IF CHARACTER IS TO BE INCLUDED ; ; REGISTERS ALTERED: R0, R3, R4 ;- ; OOBCK2: ADD #E.VHDR,R3 ;;;POINT TO OOB BUFFER HEADER ;;;ASSUME THIS IS A TEP, NOT ACB ASSUME E.VHDR,A.PRM+16 ;;;NOTE:CODE ASSUMES OOB HEADER IMMEDIATELY ;;;FOLLOWS OOB BIT MASKS IN THE AST ASSUME A.CBL,E.VSIZ TST E.VSIZ-E.VHDR(R3) ;;;ACB OR TEP? BNE 15$ ;;;IF NE, TEP ADD #4,R3 ;;;POINT TO ACB OOB HEADER 15$: MOV R4,-(SP) ;;;SAVE BITMASK POINTER CALL PCBUF ;;;PUT CHARACTER IN OOB BUFFER MOV (SP)+,R4 ;;;GET BACK BITMASK POINTER BCC 17$ ;;;CC -> ROOM IN BUFFER TST (SP)+ ;;;ELSE, POP OFF RETURN ADDRESS MOV (SP)+,R0 ;;;RESTORE R0 CALLR I1BEEP ;;;WARN USER THAT NO ROOM IN BUFFER 17$: TST (R4)+ ;;;SKIP TO NEXT BITMASK DOUBLEWORD BIT $BTMSK(R0),(R4)+ ;;;IS CHARACTER A "CLEAR" OOB? BNE 20$ ;;;IF NE, NO...CHECK FOR "INCLUDE" MOV R2,-(SP) ;;;SAVE CHARACTER CALL I1CTX1 ;;;CLEAR OOB MUST CLEAR TABUF CALL I1CTQ ;;;ALSO RESTART OUTPUT MOV (SP)+,R2 ;;;RESTORE CHARACTER TO R2 .IF DF T$$SPL MOV #120000,R3 ;;;GET UCBX POINTER .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R3 ;;;GET UCBX POINTER .ENDC ;T$$SPL ASSUME U.TCI,0 TST (R3) ;;;DO WE HAVE A CURRENT PACKET? BEQ 30$ ;;;BR IF NO MOV R2,-(SP) ;;;GET CHARACTER SWAB (SP) ;;;INTO HIGH BYTE MOVB #IS.OOB,(SP) ;;;INDICATE THAT THIS WILL TERMINATE READ MOV (SP)+,@(R3) ;;;SET STATUS BR 30$ ;;;SKIP SINCE "CLEAR" OOB CAN'T BE "INCLUDE" 20$: TST (R4)+ ;;;SKIP TO NEXT BITMASK DOUBLEWORD BIT $BTMSK(R0),(R4) ;;;IS CHARACTER OUT-OF-BAND INCLUDE? BNE 40$ ;;;IF NE, YES...SKIP TO FINISH OOB CHARACTER 30$: CLR R4 ;;;INDICATE CHARACTER IS NOT INCLUDED 40$: MOV #FR.OOB,R3 ;;;SET REQUEST TYPE FOR OUT-OF-BAND FORK MOV R4,-(SP) ;;;SAVE R4 CALL FORK ;;;REQUEST THE FORK MOV (SP)+,R4 ;;; 60$: TST R4 ;;;CLEAR CARRY AND SEE IF OOB OR INCL BEQ 70$ ;;;IF EQ, NOT OOB OR NOT INCLUDE SEC ;;;SET CARRY IF OOB OR INCL 70$: RETURN ;;;ALL DONE .DSABLE LSB .ENDC ;T$$OOB .PAGE .SBTTL . IPROC - SEE IF AN INPUT CHARACTER CAN BE PROCESSED NOW ; ;+ ; **-IPROC - DETERMINE WHETHER AN INPUT CHARACTER CAN BE PROCESSED NOW ; ; INPUTS: ; R2 = CHARACTER ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; CC-C = 0 IF THE INPUT CHARACTER CAN BE PROCESSED NOW ; = 1 IF CHARACTER CAN NOT BE PROCESSED NOW ; ; CC-Z = 1 IF THE CHARACTER IS TO BE THROWN AWAY ; ; REGISTERS ALTERED: R2, R3, R4 ;- ; .ENABL LSB IPROC:: BIT #S1.DSI,(R5) ;;;IS INPUT PROCESSING DISABLED? BNE RETCS ;;;IF NE, YES...CAN'T PROCESS NOW .IF DF B$$MAP CALL RSDPRC ;;;IO.RSD OUTSTANDING? CLZ ;;;DON'T THROW THE CHARACTER AWAY BCC RETCS ;;;Y - CAN'T PROCESS NOW, JUMP .ENDC ;B$$MAP CMP R2,#CH.CTC ;;;IS CHARACTER ^C (AND NO HARD RECEIVE ERROR)? BNE 70$ ;;;IF NE, NO...SKIP .SBTTL . CHARACTER IS CONTROL-C ; ; CHARACTER IS CTRL-C ; .IF DF T$$SCA BIT #S3.TME,4(R5) ;;;IS TERMINAL MANG'T ENABLED? BNE 70$ ;;;IF NE, YES, CTL C IS NORMAL CHARACTER .ENDC ;T$$SCA ASSUME S1.IBY,200 TSTB (R5) ;;;IS INPUT BUSY? BMI 30$ ;;;IF MI, YES...SKIP ; ; CHARACTER IS CONTROL-C AND INPUT IS NOT BUSY. SEE IF IT SHOULD CAUSE AN ; UNSOLICITED INPUT AST. ; .IF DF T$$CCA .IF DF T$$SPL TST U.ATT-U.TSTA(R5) ;;;TERMINAL ATTACHED? BEQ 60$ ;;;BR IF NO MOV #120000,R4 ;;;SET VIRTUAL ADDRESS OF UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET UCBX IF THERE IS ONE BEQ 60$ ;;;IF EQ, THERE ISN'T ONE...SKIP .ENDC ;T$$SPL MOV U.TAST(R4),R3 ;;;GET AST BLOCK IF THERE IS ONE BEQ 20$ ;;;IF EQ, NO AST SET UP...SKIP BITB #TF.XCC,A.PRM+5(R3) ;;;WANT CONTROL-C PASSED TO THE AST? BNE 60$ ;;;IF NE, NO...SKIP 10$: TST A.PRM+6(R3) ;;;NEED TO CHECK FOR LOCKED AST BLOCK? BEQ 100$ ;;;IF EQ, YES...CHECK THAT POSSIBILITY BITB #AF.QUE,A.PRM+5(R3) ;;;IS ACB CURRENTLY IN THE AST QUEUE? BNE RETCS ;;;IF NE, YES...CAN'T PROCESS ^C NOW BR 110$ ;;;OTHERWISE, SKIP TO TRIGGER AST 20$: .IFTF ;T$$CCA BIT #S3.PTH!S3.RAL,4(R5) ;;;TERMINAL IN PASSTHRU OR BINARY MODE? BNE RETCS ;;;IF NE, YES...PUT ^C IN TYPE-AHEAD BUFFER BR 60$ ;;;OTHERWISE, SEE IF TERMINAL IS SLAVED ; ; CHARACTER IS CONTROL-C AND INPUT IS BUSY. ; 1. IF DOING IO.RAL OR IO.RST, OR IF ALREADY DOING UNSOLICITED ; INPUT, TRY TO PROCESS IMMEDIATELY (DEPENDENT ON OUTPUT BUSY ; AND ECHOING REQUIREMENT). ; 2. ELSE, IF TERMINAL IS SLAVED, DISCARD THE CHARACTER. ; 3. ELSE, IF AN AST IS NOT SPECIFIED, FORK TO ABORT SOLICITED ; INPUT AND START AN UNSOLICITED INPUT. ; 4. ELSE, QUEUE AN AST ; 30$: BIT #S1.PTH!S1.RSP,(R5) ;;;DOING READ WITH SPEC. PROC.OR PASSTHRU? BNE 80$ ;;;IF NE, YES...SKIP .IF DF T$$RPR BIT #S5.RPO,U.TST5-U.TSTA(R5) ;;;PROMPT OUTPUT IN PROGRESS? BNE RETCS ;;;IF NE, YES...CAN'T PROCESS NOW .ENDC ASSUME S1.USI,100000 TST (R5) ;;;ARE WE DOING UNSOLICITED INPUT? BPL 40$ ;;;IF PL, NO...SKIP ; ; CHARACTER IS CONTROL-C, AND AN UNSOLICITED INPUT IS BUSY. ; 1. IF OUTPUT IS NOT BUSY ACCEPT CTRL-C WHICH WILL RESTART THE ; UNSOLICITED INPUT. ; 2. ELSE, CANNOT PROCESS NOW SINCE UNLIKE THE PROCESSING OF ALL OTHER ; CHARACTERS, CTRL-C PROCESSING FORCES THE OUTPUT OF A PROMPT ; WITHOUT REGARD FOR THE ECHO/NOECHO STATUS OF THE TERMINAL ; BIT #S1.OBY,(R5) ;;;IS OUTPUT BUSY? BEQ RETCC ;;;IF EQ, NO...^C STARTS AN UNSOLICITED INPUT RETCS: SEC ;;;SET INDICATION WE CAN'T PROCESS CHARACTER RETURN ;;;ALL DONE ; ; CHARACTER IS CONTROL-C AND A SOLICITED INPUT IS BUSY. ; 40$: .IFT ;T$$CCA .IF DF T$$SPL MOV #120000,R4 ;;;SET VIRTUAL ADDRESS OF UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET UCBX .ENDC ;T$$SPL MOV U.TAST(R4),R3 ;;;GET AST BLOCK IF THERE IS ONE BEQ 60$ ;;;IF EQ, ASTS NOT SPECIFIED...SKIP BITB #TF.XCC,A.PRM+5(R3) ;;;PASS ^C TO AST? BNE 60$ ;;;IF NE, NO...SKIP BITB #AF.QUE,A.PRM+5(R3) ;;;IS AN AST ALREADY QUEUED? BEQ 10$ ;;;IF EQ, NO...ASTS MAY BE POSSIBLE .ENDC ;T$$CCA 50$: TST (SP)+ ;;;POP RETURN ADDRESS TO TOSS THE CHARACTER RETURN ;;;RETURN BACK TO CALLER'S CALLER 60$: ASSUME U2.SLV,200 TSTB U.CW2-U.TSTA(R5) ;;;IS THIS A SLAVED TERMINAL? BMI 50$ ;;;IF MI, YES...THROW AWAY THE ^C .IF DF A$$CLI&C$$CTC BIT #S3.CTC,4(R5) ;;;DOES THIS TERMINAL EXPECT NOTIFICATION BEQ 130$ ;;;IF EQ, NO..CONTINUE WITH NORMAL PROCESSING MOV U.MUP-U.TSTA(R5),R3 ;;;GET THIS CLI OFFSET INTO CPB TABLE BIC #^CUM.CLI,R3 ;;;ELIMINATE ALL BUT THE OFFSET MOV $CPTBL(R3),R3 ;;;POINT TO CPB FOR THIS TERMINAL BIT #CP.CTC,C.PSTS(R3) ;;;DOES THIS CLI ACCEPT NOTIFICATION PACKET? BEQ 130$ ;;;IF EQ, NO...CONTINUE WITH NORMAL PROCESSING MOV #FR.KIL,R3 ;;;FORK TO QUEUE NOTIFICATION PACKET CALL FORK ;;;QUEUE FORK REQUEST - THIS CODE ASSUMES... ;;; ...THAT FPKIL IS ENTERED WITH BIT... ;;; ...UM.KIL CLEARED IN U.MUP CALL GCTAB ;;;CHECK FOR ^C IN TYPE-AHEAD BUFFER BCS 50$ ;;;IF CS BUFFER IS CLEAR CMPB R2,#CH.CTC ;;;MAKE SURE IT IS THE ^C BNE 50$ ;;;IF NE, IT ISN'T...IGNORE THE CHARACTER CALL RCTAB ;;;REMOVE CHARACTER FROM TYPE-AHEAD BUFFER BR 50$ ;;;RETURN FOR NEXT FORK QUEUE ROUTINE .IFF ;A$$CLI&C$$CTC BR 130$ ;;;N - JUMP .ENDC ;A$$CLI&C$$CTC .PAGE .SBTTL . CHARACTER IS NOT CONTROL-C ; ; CHARACTER IS NOT CONTROL-C ; 70$: ASSUME S1.IBY,200 TSTB (R5) ;;;IS INPUT BUSY? BPL 90$ ;;;IF PL, NO...SKIP ; ; CHARACTER IS NOT CONTROL-C AND INPUT IS BUSY: ; 1. IF ECHO IS REQUIRED AND OUTPUT IS BUSY, RETURN ; WITH CC-C = 1 (CHARACTER CAN NOT BE PROCESSED NOW). ; 2. IF OUTPUT IS BUSY WITH THE PROMPT OF A READ WITH PROMPT, ; THE READ HAS NOT STARTED YET SO RETURN WITH CC-C = 1 ; (CHARACTER CANNOT BE PROCESSED NOW). ; 3. ELSE, RETURN WITH CC-C =0 (CHARACTER CAN BE PROCESSED NOW). ; 80$: BIT #S1.OBY,(R5) ;;;OUTPUT BUSY? BEQ RETCC ;;;IF EQ, NO...PROCESS CHARACTER BIT #S1.RNE,(R5) ;;;IS LINE IN NOECHO MODE? BEQ RETCS ;;;IF EQ, NO...CAN'T PROCESS NOW .IF DF T$$RPR BIT #S5.RPO,U.TST5-U.TSTA(R5) ;;;PROMPT OUTPUT IN PROGRESS? BNE RETCS ;;;IF NE, YES...CAN'T PROCESS NOW .ENDC ;T$$RPR RETCC: CLC ;;;CLEAR CARRY RETURN ;;;RETURN ; ; CHARACTER IS NOT CONTROL-C AND INPUT IS NOT BUSY: ; 1. IF UNSOLICITED INPUT ASTS ARE SET UP, REQUEST A FORK TO GIVE ONE. ; NOTE A SPECIAL CASE - IF THE AST BLOCK IS "LOCKED", DO NOT FORK. ; THE AST BLOCK IS LOCKED WHEN IT IS STILL IN THE TASK'S AST QUEUE, ; OR WHEN TF.NOT WAS SPECIFIED AT ATTACH AND THE TASK HAS NOT DONE ; A READ SINCE THE PREVIOUS AST WAS QUEUED. ; 2. ELSE, IF THE TERMINAL IS ATTACHED, RETURN. ; 3. ELSE, FORK TO START AN UNSOLICITED INPUT. ; ; IN ALL OF THE ABOVE CASES, RETURN WITH CC-C = 1 TO INDICATE THAT THE ; CHARACTER CAN NOT BE PROCESSED IMMEDIATELY. ; 90$: TST U.ATT-U.TSTA(R5) ;;;IS THE TERMINAL ATTACHED? .IF DF T$$CCA BEQ 120$ ;;;IF EQ, NO...SKIP .IF DF T$$SPL MOV #120000,R4 ;;;SET VIRTUAL ADDRESS OF UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET UCBX (TERMINAL IS ATTACHED ;;;SO THERE MUST BE ONE) .ENDC ;T$$SPL MOV U.TAST(R4),R3 ;;;GET AST BLOCK ADDRESS BEQ RETCS ;;;IF EQ, NONE...NO AST SET UP TST A.PRM+10(R3) ;;;ASTS WANTED FOR OTHER THAN ^C? BEQ RETCS ;;;IF EQ, NO...RETURN 100$: BITB #AF.LCK!AF.QUE,A.PRM+5(R3) ;;;IS ACB LOCKED OR QUEUED? BNE RETCS ;;;IF NE, YES...CAN'T REQUEST IT NOW 110$: .IF DF T$$RED BIT #S5.BCC!S5.DAO!S5.VER,R2 ;;;WAS HARD RECEIVE ERROR DETECTED? BNE 50$ ;;;IF NE, YES...THROW AWAY CHARACTER .ENDC ;T$$RED MOV #FR.AST,R3 ;;;SET UP TO FORK FOR UNSOLICITED INPUT AST BR 140$ ;;;SKIP .IFF ;T$$CCA BNE RETCS ;;;IF NE, TERMINAL IS ATTACHED...CAN'T PROCESS .ENDC ;T$$CCA 120$: TSTB U.CW2-U.TSTA(R5) ;;;IS THIS A SLAVED TERMINAL? BPL 125$ ;;;DO NOT DISCARD THE CHARACTER BIT #4,$TTPRM ;;;CHECK IF WE USE TYPEAHEAD BUFFER FOR SLAVED ;;;TERMINALS BEQ 50$ ;;;THROW THE CHARACTER AWAY BR RETCS ;;;MOVE CHARACTER IN TYPEAHEAD BUFFER 125$: ;;;REFERENCE LABEL .IF DF T$$SER BIT #UM.CMD,U.MUP-U.TSTA(R5) ;;;COMMAND ALREADY IN PROGRESS? BNE RETCS ;;;IF NE, YES...CAN'T PROCESS NOW .ENDC ;T$$SER .IF DF T$$IDO TST $MCRPT ;;;IS THE MCR DISPATCHER INSTALLED? BEQ RETCS ;;;IF EQ, YES...CAN'T PROCESS IT NOW .ENDC ;T$$IDO 130$: .IF DF T$$MOD BITB #US.DSB,U.STS-U.TSTA(R5) ;;;LINE DISABLED? BNE 50$ ;;;IF NE, YES...DON'T START UNSOLICITED INPUT .ENDC ;T$$MOD MOV #FR.SUI,R3 ;;;FORK TO START AN UNSOLICITED INPUT 140$: CALL FORK ;;;QUEUE THE FORK REQUEST BR RETCS ;;;RETURN TO INDICATE WE CAN'T PROCESS IT NOW .DSABL LSB .PAGE .SBTTL . PCTAB - PUT CHARACTER IN TYPE-AHEAD BUFFER ; ;+ ; **-PCTAB - PUT A CHARACTER INTO THE TYPE-AHEAD BUFFER. ; ; THIS ROUTINE PLACES A CHARACTER INTO A TERMINAL'S TYPE-AHEAD BUFFER. ; ; INPUTS: ; R2 = CHARACTER ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; CC-C = 0 IF CHARACTER SUCCESSFULLY STORED IN BUFFER ; = 1 IF CHARACTER WAS NOT STORED DUE TO FULL BUFFER ; ; REGISTERS MODIFIED: R3, R4 ;- ; .ENABL LSB PCTAB: .IF DF T$$SPL MOV #120000+U.TTBF,R3 ;;;SET TABUF POINTER .IFF ;T$$SPL MOV U.TTAB-U.TSTA(R5),R3 ;;;GET TABUF POINTER BNE 10$ ;;;IF NE...THERE IS A BUFFER MOVB R2,U.TTAB+1-U.TSTA(R5) ;;;STORE CHAR. IN SINGLE-CHAR. TABUF INCB U.TTAB-U.TSTA(R5) ;;;MARK THE TABUF AS BEING FULL CLC ;;;SHOW SUCCESS STATUS RETURN ;;;ALL DONE 10$: BIT #1,R3 ;;;IS THIS A SINGLE CHARACTER BUFFER? SEC ;;;ASSUME IT IS (AND IN USE) SO SET ERROR FLAG BNE 20$ ;;;IF NE, IT IS...RETURN WITH ERROR .ENDC ;T$$SPL CALL PCBUF ;;;PUT CHARACTER IN BUFFER BCS 20$ ;;;IF CS, BUFFER IS FULL CALL SNDXOF ;;;SEE IF WE NEED TO SEND AN XOFF CLC ;;;RETURN WITH SUCCESS INDICATION RETURN ;;;ALL DONE .PAGE .SBTTL . PCBUF - PUT CHARACTER INTO STANDARD FORMAT BUFFER ; ;+ ; **-PCBUF - PUT A CHARACTER INTO A STANDARD FORMAT BUFFER ; ; THIS ROUTINE PLACES A CHARACTER INTO A BUFFER FORMATTED AS FOLLOWS: ; ; +---------------+---------------+ ; | RETRIEVAL PTR | STORE PTR | ; +---------------+---------------+ ; | BUFFER SIZE | CHARACTER CNT | ; +---------------+---------------+ ; | CHARACTER BUFFER | ; \ \ ; +-------------------------------+ ; ; INPUTS: ; R2 = CHARACTER ; R3 => TOP OF STANDARD FORMAT BUFFER ; ; OUTPUTS: ; CC-C = 0 IF CHARACTER SUCCESSFULLY STORED IN BUFFER ; = 1 IF CHARACTER WAS NOT STORED DUE TO FULL BUFFER ; ; REGISTERS MODIFIED: R4 ;- ; PCBUF: CLR R4 ;;;PREPARE FOR BYTE TRANSFER BISB (R3)+,R4 ;;;GET OFFSET WHERE TO STORE THE CHARACTER INC R3 ;;;SKIP OVER RETRIEVAL POINTER CMPB (R3)+,(R3)+ ;;;IS THE BUFFER FULL (COUNT = SIZE)? SEC ;;;ASSUME YES AND SET ERROR FLAG BEQ 20$ ;;;IF EQ, YES...RETURN ERROR STATUS ADD R3,R4 ;;;SET POINTER IN BUFFER TO STORE CHARACTER MOVB R2,(R4) ;;;STORE CHARACTER INC -(R3) ;;;COUNT THE CHARACTER INC -(R3) ;;;UPDATE STORE POINTER CMPB 3(R3),(R3) ;;;TIME TO WRAP (STORE = SIZE)? (CLEAR CC-C) BNE 20$ ;;;IF NE, NO...ALL DONE CLRB (R3) ;;;ELSE, SET POINTER AT START OF BUFFER 20$: RETURN ;;;ALL DONE .DSABL LSB .PAGE .SBTTL . GCTAB - GET A CHARACTER FROM THE TYPE-AHEAD BUFFER ; ;+ ; GCTAB - GET A CHARACTER FROM THE TYPE-AHEAD BUFFER. ; ; INPUTS: ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; CC-C = 0 IF CHARACTER WAS OBTAINED FROM THE BUFFER ; = 1 IF THE BUFFER WAS EMPTY ; R2 = CHARACTER RETRIEVED FROM THE BUFFER (NOTE THAT THE CHARACTER ; IS NOT REMOVED FROM THE BUFFER!) ; IF THERE IS ANY UNPROCESSED DEFAULT INPUT, RETURN THE NEXT CHARACTER ; OF IT IN R2 AND WITH CC-C = 0 BEFORE CHECKING THE TYPEAHEAD BUFFER ; ; REGISTERS ALTERED: R2, R3, R4 ;- ; .PSECT MAP5 GCTAB:: .IF DF T$$EIO ASSUME S6.RDI,100000 TST U.TST6-U.TSTA(R5) ;;;LOOKING FOR DEFAULT INPUT? BPL 3$ ;;;N - JUMP .IF DF T$$SPL MOV #120000,R4 ;;;SET VIRTUAL ADDRESS OF UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET UCBX .IFTF ;T$$SPL CLR R2 ;;;PREVENT FUTURE SIGN EXTENSION AND CLEAR CC-C BIT #S1.IBF,@R5 ;;;IS DEFAULT INPUT BUFFERED? BNE 1$ ;;;Y - JUMP .IFT ;T$$SPL MOV U.TDIP(R4),KISAR6 ;;;MAP USER'S DEFAULT INPUT BUFFER BISB @U.TDIP+2(R4),R2 ;;;GET A CHARACTER FROM IT .IFF ;T$$SPL MOV U.TDIP+2(R4),R3 ;;;GET POINTER TO NEXT CHARACTER MOV U.TDIP(R4),KISAR6 ;;;MAP USER'S BUFFER (MAY UNMAP UCBX) BISB @R3,R2 ;;;GET A CHARACTER .ENDC ;T$$SPL MOV $DALED,KISAR6 ;;;REMAP DRIVER RETURN ;;;RETURN WITH CHARACTER IN R2 AND CC-C CLEAR 1$: BISB @U.TDIP+2(R4),R2 ;;;GET A CHARACTER FROM DEFAULT INPUT BUFFER RETURN ;;;RETURN WITH CHARACTER IN R2 AND CC-C CLEAR .ENDC ;T$$EIO 3$: ;;;REFERENCE LABEL .IF DF T$$SPL MOV #120000+U.TTBF+1,R2 ;;;POINT TO TABUF RETRIEVE POINTER CLR R3 ;;;PREPARE FOR BYTE TRANSFER BISB (R2)+,R3 ;;;GET RETRIEVE POINTER & POINT TO ACTIVE COUNT .IFF ;T$$SPL MOV R5,R3 ;;;POINT TO CELL CONTAINING THE... ADD #U.TTAB-U.TSTA,R3 ;;; ...ADDRESS OF THE TABUF (ALSO CLEARS CC-C) MOV (R3),R2 ;;;GET TABUF POINTER BEQ 5$ ;;;IF EQ, NOT ONE...INDICATE BUFFER IS EMPTY BITB #1,(R3)+ ;;;IS THIS THE SINGLE CHARACTER TABUF? BNE 10$ ;;;IF NE, YES...SKIP INC R2 ;;;POINT TO RETRIEVE POINTER MOVB (R2)+,R3 ;;;GET RETRIEVE POINTER & POINT TO ACTIVE COUNT .IFTF ;T$$SPL TSTB (R2)+ ;;;IS THE TABUF EMPTY? BNE 7$ ;;;IF EQ, YES...RETURN WITH THAT INDICATED 5$: JMP RETCS 7$: ADD R2,R3 ;;;MAKE POINTER IN BUFFER INC R3 ;;;POINT TO NEXT CHARACTER TO RETRIEVE .IF DF T$$RED CMPB -(R2),#1 ;;;LAST CHARACTER IN TABUF? BNE 10$ ;;;IF NE, NO...SKIP MOV U.TST5-U.TSTA(R5),R2 ;;;GET HARD RECEIVE ERROR FLAGS BIC #^C,R2 ;;;CLEAR IRRELEVANT BITS BR 20$ ;;;RETURN WITH FLAGS AND CC-C CLEAR (FROM CMPB) .ENDC ;T$$RED 10$: CLR R2 ;;;CLEAR R2 AND CC-C 20$: BISB (R3),R2 ;;;PUT CHARACTER IN LOW BYTE RETURN ;;;RETURN WITH CHARACTER .PAGE .SBTTL . RCTAB - REMOVE A CHARACTER FROM THE TYPE-AHEAD BUFFER ; ;+ ; RCTAB - REMOVE A CHARACTER FROM THE TYPE-AHEAD BUFFER. ; MUST BE CALLED ONLY IF THERE IS A CHARACTER TO REMOVE!!! ; IF THERE IS UNPROCESSED DEFAULT INPUT, DECREMENT CHARACTER COUNT LEFT ; ; INPUTS: ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: NONE ; ; REGISTERS ALTERED: R3, R4 ;- ; .PSECT MAP5.6 RCTAB:: .IF DF T$$EIO ASSUME S6.RDI,100000 TST U.TST6-U.TSTA(R5) ;;;LOOKING FOR DEFAULT INPUT? BPL 3$ ;;;N - JUMP INC U.TDIP+2(R4) ;;;POINT TO NEXT DEFAULT INPUT CHARACTER DEC U.TDIC(R4) ;;;ONE LESS DEFAULT INPUT CHARACTER TO GO BEQ 1$ ;;;BRANCH IF ALL DONE BIT #S1.IBF,@R5 ;;;ARE DEFAULT INPUT CHARACTERS BUFFERED? BEQ 2$ ;;;N - RETURN DEC U.TDIP(R4) ;;;REDUCE COUNT OF CHARACTERS IN BUFFER BNE 2$ ;;;BUFFER IS NOT YET EMPTY - JUMP MOV #T$$BFL-4,U.TDIP(R4) ;;;BUFFER IS EMPTY - RESET CHARACTER COUNT MOV U.TDIP+2(R4),R3 ;;;GET POINTER ONE CHARACTER PAST END OF BUFFER SUB #T$$BFL,R3 ;;;BACK UP TO BUFFER LINK WORD MOV @R3,U.TDIP+2(R4);;;SET NEW CURRENT BUFFER ADD #4,U.TDIP+2(R4) ;;;POINT TO FIRST CHARACTER WITHIN IT RETURN 1$: BIC #S6.RDI,U.TST6-U.TSTA(R5);;;NO MORE DEFAULT INPUT TO PROCESS 2$: RETURN .ENDC ;T$$EIO 3$: ;;;REFERENCE LABEL .IFT ;T$$SPL MOV #120000+U.TTBF+1,R3 ;;;POINT TO TABUF RETRIEVE POINTER .IFF ;T$$SPL MOV U.TTAB-U.TSTA(R5),R3 ;;;GET START OF TABUF BIT #1,R3 ;;;IS THIS THE SINGLE CHARACTER TABUF? BNE 20$ ;;;IF NE, YES...SKIP INC R3 ;;;POINT TO RETRIEVE POINTER .ENDC ;T$$SPL INCB (R3) ;;;UPDATE RETRIEVE POINTER CMPB (R3)+,1(R3) ;;;DID WE WRAP AROUND? BNE 10$ ;;;IF NE, NO...SKIP CLRB -1(R3) ;;;ELSE, RESET POINTER TO START OF BUFFER 10$: CALL SNDXON ;;;POSSIBLY SEND AN XON DECB (R3) ;;;UPDATE COUNT OF BYTES LEFT TO GET .IF DF T$$RED BEQ 30$ ;;;IF EQ, LAST CHARACTER REMOVED...SKIP .IFTF ;T$$RED RETURN ;;;ALL DONE .IF NDF T$$SPL 20$: CLR U.TTAB-U.TSTA(R5) ;;;MARK SINGLE-CHARACTER TABUF AS EMPTY .ENDC ;NDF T$$SPL .IFT ;T$$RED 30$: BIC #S5.BCC!S5.DAO!S5.VER,U.TST5-U.TSTA(R5) ;;;CLEAR ERROR FLAGS .ENDC ;T$$RED RETURN ;;;ALL DONE .PAGE .SBTTL . SNDXOF - SEND XOFF IF TYPE-AHEAD BUFFER IS NEARLY FULL ; ;+ ; SNDXOF - SEND XOFF IF HOSTSYNC ENABLED AND TABUF NEARLY FULL. ; ; INPUTS: ; R3 => TOP OF TYPE-AHEAD BUFFER ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: NONE ; ; REGISTERS ALTERED: R4 ;- ; .ENABL LSB SNDXOF: BIT #S4.HSY,6(R5) ;;;HOST SYNCHRONIZATION ENABLED? BEQ 20$ ;;;IF EQ, NO...JUST RETURN .IF DF T$$SPL MOVB U.TBSZ-U.TSTA(R5),R4 ;;;GET SIZE OF TYPE-AHEAD BUFFER SUB #XHIPNT,R4 ;;;COMPUTE CHAR. COUNT AT WHICH TO SEND XOFF CMPB 2(R3),R4 ;;;DID WE REACH THE HIGH THRESHOLD POINT? .IFF ;T$$SPL CMPB 2(R3),#XHIPNT ;;;DID WE REACH THE HIGH THRESHOLD POINT? .ENDC ;T$$SPL BNE 20$ ;;;IF NE, NO...DON'T SEND XOFF BIS #S5.OXF!S5.XOF,U.TST5-U.TSTA(R5) ;;;REQUEST XOFF OUTPUT & STATE BR 10$ ;;;JOIN COMMON CODE .SBTTL . SNDXON - SEND XON IF TYPE-AHEAD BUFFER IS NEARLY EMPTY ; ;+ ; SNDXON - SEND XON IF XOFF PREVIOUSLY SENT AND TABUF NEARLY EMPTY. ; ; INPUTS: ; R3 => TABUF ACTIVE BYTE COUNT BEFORE BEING DECREMENTED ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: NONE ; ; REGISTERS ALTERED: R4 ;- ; SNDXON: BIT #S5.OXF,U.TST5-U.TSTA(R5) ;;;PREVIOUSLY OUTPUT AN XOFF? BEQ 20$ ;;;IF EQ, NO...ALL DONE CMPB (R3),#XLOPNT+1 ;;;DID WE REACH THE LOW THRESHOLD POINT? BHI 20$ ;;;IF HI, NO...DON'T SENT XON YET BIC #S5.OXF,U.TST5-U.TSTA(R5) ;;;RESET XOFF STATUS BIS #S5.XON,U.TST5-U.TSTA(R5) ;;;SET XON STATUS BIT 10$: MOV R2,-(SP) ;;;SAVE REGISTERS DESTROYED BY CTRD ROUTINE MOV R3,-(SP) ;;; MOV R4,-(SP) ;;;DESTROYED BY PORT DRIVER ASSUME CT.STA,0 CLR R2 ;;;SET INDEX FOR "START OUTPUT" CALL CTRD ;;;CALL CONTROLLER DEPENDENT ROUTINE MOV (SP)+,R4 ;;; MOV (SP)+,R3 ;;;RESTORE SAVED REGISTERS MOV (SP)+,R2 ;;; 20$: RETURN ;;;ALL DONE .DSABL LSB .PAGE .SBTTL . ABOX/ABOXL - ABORT CURRENT TERMINAL OUTPUT ; ;+ ; ABOXL - LOCK OUT INTERRUPTS AND CALL CONTROLLER-DEPENDENT ROUTINE TO ; ABORT THE CURRENT OUTPUT. ;- ; .PSECT MAP5 ABOXL:: CALL LOCKI ;LOCK OUT INTERRUPTS ABOX: MOV #CT.ABO,R2 ;;;SET INDEX FOR "ABORT OUTPUT" ;;;FALL THRU TO "CTRD" .SBTTL . CTRD - CALL CONTROLLER DEPENDENT ROUTINE ; ;+ ; CTRD - CALL CONTROLLER DEPENDENT ROUTINE. ; ; INPUTS: ; R2 = ROUTINE INDEX: ; 0 - START OUTPUT ; 2 - ABORT OUTPUT ; 4 - RESUME OUTPUT ; 6 - STOP OUTPUT ; 10 - POWER-UP (RSX-11M) ; 12 - MODEM TIMER (RSX-11M) ; 14 - GET/SET LINE PARAMETERS (RSX-11M) ; 10 - MODEM TIMER (RSX-11M-PLUS) ; 12 - CONTROLLER POWER-UP (RSX-11M-PLUS) ; 14 - UNIT POWER-UP (RSX-11M-PLUS) ; 16 - CONTROLLER ONLINE (RSX-11M-PLUS) ; 20 - CONTROLLER OFFLINE (RSX-11M-PLUS) ; 22 - UNIT ONLINE (RSX-11M-PLUS) ; 24 - UNIT OFFLINE (RSX-11M-PLUS) ; 26 - GET/SET LINE PARAMETERS (RSX-11M-PLUS) ; R5 => U.TSTA OF TERMINAL UCB ; ; OUTPUTS: ; THE CONTROLLER DEPENDENT ROUTINE IS CALLED WITH: ; R2 = PHYSICAL UNIT NUMBER * 2 (ONLY IF MULTIPLEXERS IN SYSTEM) ; R3 => CSR ADDRESS FOR TERMINAL'S CONTROLLER ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL'S UCB ; ; REGISTERS ALTERED: R2, R3, R4 ;- ; CTRD:: .IF DF R$$MPL MOV U.SCB-U.TSTA(R5),R3 ;;;GET SCB FOR THIS UCB MOV S.KRB(R3),R3 ;;;GET KRB MOVB K.PRM(R3),R4 ;;;GET CONTROLLER TYPE ADD CTBL(R4),R2 ;;;POINT TO DISPATCH TABLE FOR CONTROLLER TYPE MOV (R3),R3 ;;;GET CSR .IFF ;R$$MPL MOVB U.CTYP-U.TSTA(R5),R4 ;;;GET CONTROLLER TYPE ADD CTBL(R4),R2 ;;;POINT TO DISPATCH TABLE FOR CONTROLLER TYPE MOV U.SCB-U.TSTA(R5),R3 ;;;GET SCB MOV S.CSR(R3),R3 ;;;GET CSR .ENDC ;R$$MPL .IF DF T$$SPL MOV #120000,R4 ;;;SET VIRTUAL ADDRESS OF UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;;;GET UCBX (IF THERE IS ONE) .ENDC ;T$$SPL .IF DF T$$MUX MOV (R2),-(SP) ;;;PUSH ROUTINE ADDRESS MOVB U.UNIT-U.TSTA(R5),R2 ;;;GET PHYSICAL UNIT NUMBER ASL R2 ;;;MULTIPLY BY 2 CALLR @(SP)+ ;;;CALL ROUTINE AND RETURN .IFF ;T$$MUX CALLR @(R2)+ ;;;CALL ROUTINE AND RETURN .ENDC ;T$$MUX .PAGE .SBTTL . GETPIC - GET PREVIOUS CHARACTER FROM INPUT BUFFER ; ;+ ; GETPIC - GET PREVIOUS CHARACTER FROM INPUT BUFFER ; ; INPUTS: ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; CC-C = 0 IF THERE IS A PREVIOUS CHARACTER ; = 1 IF THERE IS NO CHARACTER ; R2 = CHARACTER ; R3 => CHARACTER IN THE INPUT BUFFER ; U.TIP, U.TIP+2, U.TIC AND U.TTIC "DOWN-DATED" ; (CHARACTER LOGICALLY REMOVED FROM INPUT BUFFER) ; ; REGISTERS ALTERED: R2, R3 ;- ; GETPIC: MOV R4,-(SP) ;;;SAVE UCBX POINTER ASSUME U.TCI,0 MOV (R4)+,R3 ;;;GET CURRENT PACKET (IF SOLICITED INPUT) ASSUME U.TIP,U.TCI+2 MOV (R4)+,R2 ;;;GET CURRENT BUFFER (IF BUFFERED INPUT) ADD #4,R2 ;;;POINT AT START OF DATA AREA BIT #S1.IBF,(R5) ;;;DOING BUFFERED INPUT? BNE 10$ ;;;IF NE, YES...SKIP MOV I.PRM+2(R3),R2 ;;;GET START ADDRESS OF TASK BUFFER 10$: MOV (R4),R3 ;;;GET CURRENT CHARACTER POINTER (U.TIP+2) CMP R3,R2 ;;;POINTING AT START OF (CURRENT) BUFFER? BHI 50$ ;;;IF HI, NO...ALL IS OK, SO SKIP BIT #S1.IBF,(R5) ;;;DOING BUFFERED INPUT? BEQ 30$ ;;;IF EQ, NO...RETURN WITH INPUT BUFFER EMPTY MOV U.TFIB-(R4),R3 ;;;GET FIRST INPUT BUFFER CMP R3,-(R4) ;;;ARE WE IN THE FIRST BUFFER? BEQ 30$ ;;;IF EQ, YES...EXIT WITH ERROR CLR U.TIC-U.TIP(R4) ;;;CLEAR U.TIC (SWITCHING BACK TO PREVIOUS ;;;BUFFER, WHICH IS FULL JUST NOW) ADD -(R2),U.TTIC-U.TIP(R4) ;;;UPDATE U.TTIC ; ; SCAN LIST OF INPUT BUFFERS UNTIL THE BUFFER PREVIOUS TO THE ONE POINTED ; TO BY R2 IS FOUND. ; 20$: CMP (R3),(R4) ;;;POINTING TO OUR BUFFER? BEQ 40$ ;;;IF EQ, YES...SKIP MOV (R3),R3 ;;;ELSE GET POINTER TO NEXT ONE BR 20$ ;;;LOOP ; ; NO CHARACTERS ARE IN THE BUFFER - EXIT WITH CC-C = 1 ; 30$: MOV (SP)+,R4 ;;;RESTORE UCBX POINTER SEC ;;;RETURN WITH CC-C = 1 RETURN ;;;ALL DONE ; ; PREVIOUS BUFFER FOUND - R3 POINTS TO IT ; 40$: MOV R3,(R4)+ ;;;MAKE THIS THE CURRENT BUFFER ADD #T$$BFL,R3 ;;;POINT JUST AFTER LAST CHAR. IN BUFFER ; ; WE NOW HAVE R3 POINTING JUST AFTER THE LAST CHARACTER IN THE INPUT ; BUFFER. THE UCBX IS UPDATED IF WE HAD TO GO TO THE PREVIOUS BUFFER. ; 50$: DEC R3 ;;;STEP BACK 1 CHARACTER MOV R3,(R4)+ ;;;UPDATE U.TIP+2 INC (R4) ;;;UPDATE U.TIC MOV (SP)+,R4 ;;;RESTORE UCBX POINTER ;;;FALL THRU TO "GETRIC" .PAGE .SBTTL . GETRIC - GET A RANDOM INPUT CHARACTER ; ;+ ; GETRIC - GET A RANDOM INPUT CHARACTER ; ; INPUTS: ; R3 => CHARACTER TO BE RETRIEVED ; R4 => UCBX FOR THE TERMINAL ; ; OUTPUTS: ; R2 = CHARACTER ; CC-C = 0 ; ; REGISTERS ALTERED: R2 ;- ; GETRIC: CALL MAPIB ;;;MAP INPUT BUFFER CLR R2 ;;;PREPARE TO RECEIVE CHARACTER AND CLEAR CC-C BISB (R3),R2 ;;;GET CHARACTER WITHOUT SIGN EXTEND PROBLEMS RETURN ;;;RETURN TO CALLER .PAGE .SBTTL . PUTNIC - PUT NEXT INPUT CHARACTER IN BUFFER ; ;+ ; PUTNIC - PUT NEXT INPUT CHARACTER IN BUFFER ; ; INPUTS: ; R2 = CHARACTER TO BE STORED ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; CHARACTER STORED IN INPUT BUFFER. ; U.TIP+2 AND U.TIC UPDATED. ; ; REGISTERS ALTERED: R3 ;- ; PUTNIC: MOV U.TIP+2(R4),R3 ;;;GET CHARACTER POINTER CALL MAPIB ;;;MAP THE INPUT BUFFER MOVB R2,(R3) ;;;STORE THE CHARACTER CALL @(SP)+ ;;;RESTORE MAPPING INC U.TIP+2(R4) ;;;UPDATE CHARACTER POINTER DEC U.TIC(R4) ;;;UPDATE CHARACTER COUNT RETURN ;;;ALL DONE .PAGE .SBTTL . MAPD - MAP DRIVER DATA SPACE ; ;+ ; MAPD - MAP DRIVER DATA SPACE ;- ; .IF DF T$$COM MAPD:: .IF NDF T$$SPL MOV #0,KDSAR5 ;;;MAP TTCOM IN D-SPACE APR 5 PAR5S==.-4 ;;;FILLED IN AT VIRGIN INITIALIZATION .ENDC ;NDF T$$SPL MOV #0,KINAR6 ;;;MAP TOP 4K OF DRIVER PAR6I==.-4 ;;;FILLED IN AT VIRGIN INITIALIZATION BR RESM ;;; .ENDC ;T$$COM .SBTTL . MAPIB - MAP INPUT BUFFER ; ;+ ; MAPIB - MAP INPUT BUFFER ; ; INPUTS: ; R4 => UCBX FOR THE TERMINAL ; R5 = U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; INPUT BUFFER MAPPED IN KISAR6 ; CALLER CALLED BACK AS A COROUTINE - WITH CC-C = 0. ; "RETURN" LEADS BACK TO THIS ROUTINE WHICH THEN RESTORES ; KISAR6 AND RETURNS TO CALLER'S CALLER WITH CC-C PRESERVED. ; ; NOTE - WHEN THE CALLER IS CALLED AS COROUTINE, THE UCBX MAY NOT BE MAPPED! ; ; REGISTERS ALTERED: NONE ;- ; MAPIB: CLC ;;;ASSUME WANT CC-C CLEAR BIT #S1.IBF,(R5) ;;;DOING BUFFERED INPUT? BNE 10$ ;;;IF NE, YES...DON'T CHANGE MAPPING MOV U.TIP(R4),KISAR6 ;;;MAP TASK BUFFER 10$: CALL @(SP)+ ;;;CALL CALLER BACK .IF NDF T$$COM MAPD:: .ENDC ;NOT T$$COM RESM: MOV $DALED,KISAR6 ;;;RESTORE KISAR6 RETURN ;;;RETURN TO CALLER .END